// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// This library implements a kernel2kernel constant evaluation transformation.
///
/// Even though it is expected that the frontend does not emit kernel AST which
/// contains compile-time errors, this transformation still performs some
/// validation and throws a [ConstantEvaluationError] if there was a
/// compile-time errors.
///
/// Due to the lack information which is is only available in the front-end,
/// this validation is incomplete (e.g. whether an integer literal used the
/// hexadecimal syntax or not).
///
/// Furthermore due to the lowering of certain constructs in the front-end
/// (e.g. '??') we need to support a super-set of the normal constant expression
/// language.  Issue(http://dartbug.com/31799)
library fasta.constant_evaluator;

import 'dart:io' as io;

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/src/const_canonical_type.dart';
import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/norm.dart';
import 'package:kernel/src/printer.dart' show AstPrinter, AstTextStrategy;
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import 'package:kernel/target/targets.dart';

import '../fasta_codes.dart'
    show
        LocatedMessage,
        Message,
        messageConstEvalCircularity,
        messageConstEvalContext,
        messageConstEvalExtension,
        messageConstEvalFailedAssertion,
        messageConstEvalNotListOrSetInSpread,
        messageConstEvalNotMapInSpread,
        messageConstEvalNonNull,
        messageConstEvalNullValue,
        messageConstEvalStartingPoint,
        messageConstEvalUnevaluated,
        messageNonAgnosticConstant,
        messageNotAConstantExpression,
        noLength,
        templateConstEvalCaseImplementsEqual,
        templateConstEvalDeferredLibrary,
        templateConstEvalDuplicateElement,
        templateConstEvalDuplicateKey,
        templateConstEvalElementImplementsEqual,
        templateConstEvalFailedAssertionWithMessage,
        templateConstEvalFreeTypeParameter,
        templateConstEvalGetterNotFound,
        templateConstEvalInvalidType,
        templateConstEvalInvalidBinaryOperandType,
        templateConstEvalInvalidEqualsOperandType,
        templateConstEvalInvalidMethodInvocation,
        templateConstEvalInvalidPropertyGet,
        templateConstEvalInvalidStaticInvocation,
        templateConstEvalInvalidStringInterpolationOperand,
        templateConstEvalInvalidSymbolName,
        templateConstEvalKeyImplementsEqual,
        templateConstEvalNonConstantVariableGet,
        templateConstEvalUnhandledCoreException,
        templateConstEvalUnhandledException,
        templateConstEvalZeroDivisor;

import 'constant_int_folder.dart';

part 'constant_collection_builders.dart';

Component transformComponent(
    Component component,
    ConstantsBackend backend,
    Map<String, String> environmentDefines,
    ErrorReporter errorReporter,
    EvaluationMode evaluationMode,
    {required bool evaluateAnnotations,
    required bool desugarSets,
    required bool enableTripleShift,
    required bool enableConstFunctions,
    required bool errorOnUnevaluatedConstant,
    CoreTypes? coreTypes,
    ClassHierarchy? hierarchy}) {
  // ignore: unnecessary_null_comparison
  assert(evaluateAnnotations != null);
  // ignore: unnecessary_null_comparison
  assert(desugarSets != null);
  // ignore: unnecessary_null_comparison
  assert(enableTripleShift != null);
  // ignore: unnecessary_null_comparison
  assert(enableConstFunctions != null);
  // ignore: unnecessary_null_comparison
  assert(errorOnUnevaluatedConstant != null);
  coreTypes ??= new CoreTypes(component);
  hierarchy ??= new ClassHierarchy(component, coreTypes);

  final TypeEnvironment typeEnvironment =
      new TypeEnvironment(coreTypes, hierarchy);

  transformLibraries(component.libraries, backend, environmentDefines,
      typeEnvironment, errorReporter, evaluationMode,
      enableTripleShift: enableTripleShift,
      enableConstFunctions: enableConstFunctions,
      errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
      evaluateAnnotations: evaluateAnnotations);
  return component;
}

ConstantCoverage transformLibraries(
    List<Library> libraries,
    ConstantsBackend backend,
    Map<String, String> environmentDefines,
    TypeEnvironment typeEnvironment,
    ErrorReporter errorReporter,
    EvaluationMode evaluationMode,
    {required bool evaluateAnnotations,
    required bool enableTripleShift,
    required bool enableConstFunctions,
    required bool errorOnUnevaluatedConstant}) {
  // ignore: unnecessary_null_comparison
  assert(evaluateAnnotations != null);
  // ignore: unnecessary_null_comparison
  assert(enableTripleShift != null);
  // ignore: unnecessary_null_comparison
  assert(enableConstFunctions != null);
  // ignore: unnecessary_null_comparison
  assert(errorOnUnevaluatedConstant != null);
  final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
      backend,
      environmentDefines,
      evaluateAnnotations,
      enableTripleShift,
      enableConstFunctions,
      errorOnUnevaluatedConstant,
      typeEnvironment,
      errorReporter,
      evaluationMode);
  for (final Library library in libraries) {
    constantsTransformer.convertLibrary(library);
  }
  return constantsTransformer.constantEvaluator.getConstantCoverage();
}

void transformProcedure(
    Procedure procedure,
    ConstantsBackend backend,
    Map<String, String> environmentDefines,
    TypeEnvironment typeEnvironment,
    ErrorReporter errorReporter,
    EvaluationMode evaluationMode,
    {bool evaluateAnnotations: true,
    bool enableTripleShift: false,
    bool enableConstFunctions: false,
    bool errorOnUnevaluatedConstant: false}) {
  // ignore: unnecessary_null_comparison
  assert(evaluateAnnotations != null);
  // ignore: unnecessary_null_comparison
  assert(enableTripleShift != null);
  // ignore: unnecessary_null_comparison
  assert(enableConstFunctions != null);
  // ignore: unnecessary_null_comparison
  assert(errorOnUnevaluatedConstant != null);
  final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
      backend,
      environmentDefines,
      evaluateAnnotations,
      enableTripleShift,
      enableConstFunctions,
      errorOnUnevaluatedConstant,
      typeEnvironment,
      errorReporter,
      evaluationMode);
  constantsTransformer.visitProcedure(procedure, null);
}

enum EvaluationMode {
  weak,
  agnostic,
  strong,
}

class ConstantWeakener extends ComputeOnceConstantVisitor<Constant?> {
  ConstantEvaluator _evaluator;

  ConstantWeakener(this._evaluator);

  Constant? processValue(Constant node, Constant? value) {
    if (value != null) {
      value = _evaluator.canonicalize(value);
    }
    return value;
  }

  @override
  Constant? defaultConstant(Constant node) => throw new UnsupportedError(
      "Unhandled constant ${node} (${node.runtimeType})");

  @override
  Constant? visitNullConstant(NullConstant node) => null;

  @override
  Constant? visitBoolConstant(BoolConstant node) => null;

  @override
  Constant? visitIntConstant(IntConstant node) => null;

  @override
  Constant? visitDoubleConstant(DoubleConstant node) => null;

  @override
  Constant? visitStringConstant(StringConstant node) => null;

  @override
  Constant? visitSymbolConstant(SymbolConstant node) => null;

  @override
  Constant? visitMapConstant(MapConstant node) {
    DartType? keyType = computeConstCanonicalType(
        node.keyType, _evaluator.coreTypes,
        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
    DartType? valueType = computeConstCanonicalType(
        node.valueType, _evaluator.coreTypes,
        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
    List<ConstantMapEntry>? entries;
    for (int index = 0; index < node.entries.length; index++) {
      ConstantMapEntry entry = node.entries[index];
      Constant? key = visitConstant(entry.key);
      Constant? value = visitConstant(entry.value);
      if (key != null || value != null) {
        entries ??= node.entries.toList(growable: false);
        entries[index] =
            new ConstantMapEntry(key ?? entry.key, value ?? entry.value);
      }
    }
    if (keyType != null || valueType != null || entries != null) {
      return new MapConstant(keyType ?? node.keyType,
          valueType ?? node.valueType, entries ?? node.entries);
    }
    return null;
  }

  @override
  Constant? visitListConstant(ListConstant node) {
    DartType? typeArgument = computeConstCanonicalType(
        node.typeArgument, _evaluator.coreTypes,
        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
    List<Constant>? entries;
    for (int index = 0; index < node.entries.length; index++) {
      Constant? entry = visitConstant(node.entries[index]);
      if (entry != null) {
        entries ??= node.entries.toList(growable: false);
        entries[index] = entry;
      }
    }
    if (typeArgument != null || entries != null) {
      return new ListConstant(
          typeArgument ?? node.typeArgument, entries ?? node.entries);
    }
    return null;
  }

  @override
  Constant? visitSetConstant(SetConstant node) {
    DartType? typeArgument = computeConstCanonicalType(
        node.typeArgument, _evaluator.coreTypes,
        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
    List<Constant>? entries;
    for (int index = 0; index < node.entries.length; index++) {
      Constant? entry = visitConstant(node.entries[index]);
      if (entry != null) {
        entries ??= node.entries.toList(growable: false);
        entries[index] = entry;
      }
    }
    if (typeArgument != null || entries != null) {
      return new SetConstant(
          typeArgument ?? node.typeArgument, entries ?? node.entries);
    }
    return null;
  }

  @override
  Constant? visitInstanceConstant(InstanceConstant node) {
    List<DartType>? typeArguments;
    for (int index = 0; index < node.typeArguments.length; index++) {
      DartType? typeArgument = computeConstCanonicalType(
          node.typeArguments[index], _evaluator.coreTypes,
          isNonNullableByDefault: _evaluator.isNonNullableByDefault);
      if (typeArgument != null) {
        typeArguments ??= node.typeArguments.toList(growable: false);
        typeArguments[index] = typeArgument;
      }
    }
    Map<Reference, Constant>? fieldValues;
    for (MapEntry<Reference, Constant> entry in node.fieldValues.entries) {
      Reference reference = entry.key;
      Constant? value = visitConstant(entry.value);
      if (value != null) {
        fieldValues ??= new Map<Reference, Constant>.from(node.fieldValues);
        fieldValues[reference] = value;
      }
    }
    if (typeArguments != null || fieldValues != null) {
      return new InstanceConstant(node.classReference,
          typeArguments ?? node.typeArguments, fieldValues ?? node.fieldValues);
    }
    return null;
  }

  @override
  Constant? visitPartialInstantiationConstant(
      PartialInstantiationConstant node) {
    List<DartType>? types;
    for (int index = 0; index < node.types.length; index++) {
      DartType? type = computeConstCanonicalType(
          node.types[index], _evaluator.coreTypes,
          isNonNullableByDefault: _evaluator.isNonNullableByDefault);
      if (type != null) {
        types ??= node.types.toList(growable: false);
        types[index] = type;
      }
    }
    if (types != null) {
      return new PartialInstantiationConstant(node.tearOffConstant, types);
    }
    return null;
  }

  @override
  Constant? visitTearOffConstant(TearOffConstant node) => null;

  @override
  Constant? visitTypeLiteralConstant(TypeLiteralConstant node) {
    DartType? type = computeConstCanonicalType(node.type, _evaluator.coreTypes,
        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
    if (type != null) {
      return new TypeLiteralConstant(type);
    }
    return null;
  }

  @override
  Constant? visitUnevaluatedConstant(UnevaluatedConstant node) => null;
}

class ConstantsTransformer extends RemovingTransformer {
  final ConstantsBackend backend;
  final ConstantEvaluator constantEvaluator;
  final TypeEnvironment typeEnvironment;
  StaticTypeContext? _staticTypeContext;

  final bool evaluateAnnotations;
  final bool enableTripleShift;
  final bool enableConstFunctions;
  final bool errorOnUnevaluatedConstant;

  ConstantsTransformer(
      this.backend,
      Map<String, String> environmentDefines,
      this.evaluateAnnotations,
      this.enableTripleShift,
      this.enableConstFunctions,
      this.errorOnUnevaluatedConstant,
      this.typeEnvironment,
      ErrorReporter errorReporter,
      EvaluationMode evaluationMode)
      : constantEvaluator = new ConstantEvaluator(
            backend, environmentDefines, typeEnvironment, errorReporter,
            enableTripleShift: enableTripleShift,
            enableConstFunctions: enableConstFunctions,
            errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
            evaluationMode: evaluationMode);

  /// Whether to preserve constant [Field]s. All use-sites will be rewritten.
  bool get keepFields => backend.keepFields;

  /// Whether to preserve constant [VariableDeclaration]s. All use-sites will be
  /// rewritten.
  bool get keepLocals => backend.keepLocals;

  // Transform the library/class members:

  void convertLibrary(Library library) {
    _staticTypeContext =
        new StaticTypeContext.forAnnotations(library, typeEnvironment);

    transformAnnotations(library.annotations, library);

    transformLibraryDependencyList(library.dependencies, library);
    transformLibraryPartList(library.parts, library);
    transformTypedefList(library.typedefs, library);
    transformClassList(library.classes, library);
    transformExtensionList(library.extensions, library);
    transformProcedureList(library.procedures, library);
    transformFieldList(library.fields, library);

    if (!keepFields) {
      // The transformer API does not iterate over `Library.additionalExports`,
      // so we manually delete the references to shaken nodes.
      library.additionalExports.removeWhere((Reference reference) {
        return reference.node is Field && reference.canonicalName == null;
      });
    }
    _staticTypeContext = null;
  }

  @override
  LibraryPart visitLibraryPart(LibraryPart node, TreeNode? removalSentinel) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
    });
    return node;
  }

  @override
  LibraryDependency visitLibraryDependency(
      LibraryDependency node, TreeNode? removalSentinel) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
    });
    return node;
  }

  @override
  Class visitClass(Class node, TreeNode? removalSentinel) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext.forAnnotations(
        node.enclosingLibrary, typeEnvironment);
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformFieldList(node.fields, node);
      transformTypeParameterList(node.typeParameters, node);
      transformConstructorList(node.constructors, node);
      transformProcedureList(node.procedures, node);
      transformRedirectingFactoryConstructorList(
          node.redirectingFactoryConstructors, node);
    });
    _staticTypeContext = oldStaticTypeContext;
    return node;
  }

  @override
  Extension visitExtension(Extension node, TreeNode? removalSentinel) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext.forAnnotations(
        node.enclosingLibrary, typeEnvironment);
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformTypeParameterList(node.typeParameters, node);
    });
    _staticTypeContext = oldStaticTypeContext;
    return node;
  }

  @override
  Procedure visitProcedure(Procedure node, TreeNode? removalSentinel) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      node.function = transform(node.function)..parent = node;
    });
    _staticTypeContext = oldStaticTypeContext;
    return node;
  }

  @override
  Constructor visitConstructor(Constructor node, TreeNode? removalSentinel) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformInitializerList(node.initializers, node);
      node.function = transform(node.function)..parent = node;
    });
    _staticTypeContext = oldStaticTypeContext;
    return node;
  }

  @override
  Typedef visitTypedef(Typedef node, TreeNode? removalSentinel) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformTypeParameterList(node.typeParameters, node);
      transformTypeParameterList(node.typeParametersOfFunctionType, node);
      transformVariableDeclarationList(node.positionalParameters, node);
      transformVariableDeclarationList(node.namedParameters, node);
    });
    return node;
  }

  @override
  RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
      RedirectingFactoryConstructor node, TreeNode? removalSentinel) {
    // Currently unreachable as the compiler doesn't produce
    // RedirectingFactoryConstructor.
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformTypeParameterList(node.typeParameters, node);
      transformVariableDeclarationList(node.positionalParameters, node);
      transformVariableDeclarationList(node.namedParameters, node);
    });
    _staticTypeContext = oldStaticTypeContext;
    return node;
  }

  @override
  TypeParameter visitTypeParameter(
      TypeParameter node, TreeNode? removalSentinel) {
    transformAnnotations(node.annotations, node);
    return node;
  }

  void transformAnnotations(List<Expression> nodes, TreeNode parent) {
    if (evaluateAnnotations && nodes.length > 0) {
      transformExpressions(nodes, parent);
    }
  }

  void transformExpressions(List<Expression> nodes, TreeNode parent) {
    constantEvaluator.withNewEnvironment(() {
      for (int i = 0; i < nodes.length; ++i) {
        nodes[i] = evaluateAndTransformWithContext(parent, nodes[i])
          ..parent = parent;
      }
    });
  }

  // Handle definition of constants:

  @override
  FunctionNode visitFunctionNode(FunctionNode node, TreeNode? removalSentinel) {
    transformTypeParameterList(node.typeParameters, node);
    final int positionalParameterCount = node.positionalParameters.length;
    for (int i = 0; i < positionalParameterCount; ++i) {
      final VariableDeclaration variable = node.positionalParameters[i];
      transformAnnotations(variable.annotations, variable);
      Expression? initializer = variable.initializer;
      if (initializer != null) {
        variable.initializer =
            evaluateAndTransformWithContext(variable, initializer)
              ..parent = variable;
      }
    }
    for (final VariableDeclaration variable in node.namedParameters) {
      transformAnnotations(variable.annotations, variable);
      Expression? initializer = variable.initializer;
      if (initializer != null) {
        variable.initializer =
            evaluateAndTransformWithContext(variable, initializer)
              ..parent = variable;
      }
    }
    if (node.body != null) {
      node.body = transform(node.body!)..parent = node;
    }
    return node;
  }

  @override
  TreeNode visitFunctionDeclaration(
      FunctionDeclaration node, TreeNode? removalSentinel) {
    if (enableConstFunctions) {
      // ignore: unnecessary_null_comparison
      if (node.function != null) {
        node.function = transform(node.function)..parent = node;
      }
      constantEvaluator.env.addVariableValue(
          node.variable, new FunctionValue(node.function, null));
    } else {
      return super.visitFunctionDeclaration(node, removalSentinel);
    }
    return node;
  }

  @override
  TreeNode visitVariableDeclaration(
      VariableDeclaration node, TreeNode? removalSentinel) {
    transformAnnotations(node.annotations, node);

    Expression? initializer = node.initializer;
    if (initializer != null) {
      if (node.isConst) {
        final Constant constant = evaluateWithContext(node, initializer);
        constantEvaluator.env.addVariableValue(node, constant);
        initializer = node.initializer =
            makeConstantExpression(constant, initializer)..parent = node;

        // If this constant is inlined, remove it.
        if (!keepLocals && shouldInline(initializer)) {
          if (constant is! UnevaluatedConstant) {
            // If the constant is unevaluated we need to keep the expression,
            // so that, in the case the constant contains error but the local
            // is unused, the error will still be reported.
            return removalSentinel /*!*/ ?? node;
          }
        }
      } else {
        node.initializer = transform(initializer)..parent = node;
      }
    }
    return node;
  }

  @override
  TreeNode visitField(Field node, TreeNode? removalSentinel) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    TreeNode result = constantEvaluator.withNewEnvironment(() {
      Expression? initializer = node.initializer;
      if (node.isConst) {
        transformAnnotations(node.annotations, node);
        initializer = node.initializer =
            evaluateAndTransformWithContext(node, initializer!)..parent = node;

        // If this constant is inlined, remove it.
        if (!keepFields && shouldInline(initializer)) {
          return removalSentinel!;
        }
      } else {
        transformAnnotations(node.annotations, node);
        if (initializer != null) {
          node.initializer = transform(initializer)..parent = node;
        }
      }
      return node;
    });
    _staticTypeContext = oldStaticTypeContext;
    return result;
  }

  // Handle use-sites of constants (and "inline" constant expressions):

  @override
  TreeNode visitSymbolLiteral(SymbolLiteral node, TreeNode? removalSentinel) {
    return makeConstantExpression(
        constantEvaluator.evaluate(_staticTypeContext!, node), node);
  }

  bool _isNull(Expression node) {
    return node is NullLiteral ||
        node is ConstantExpression && node.constant is NullConstant;
  }

  @override
  TreeNode visitEqualsCall(EqualsCall node, TreeNode? removalSentinel) {
    Expression left = transform(node.left);
    Expression right = transform(node.right);
    if (_isNull(left)) {
      return new EqualsNull(right)..fileOffset = node.fileOffset;
    } else if (_isNull(right)) {
      return new EqualsNull(left)..fileOffset = node.fileOffset;
    }
    node.left = left..parent = node;
    node.right = right..parent = node;
    return node;
  }

  @override
  TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
    final Member target = node.target;
    if (target is Field && target.isConst) {
      // Make sure the initializer is evaluated first.
      StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
      _staticTypeContext = new StaticTypeContext(target, typeEnvironment);
      target.initializer =
          evaluateAndTransformWithContext(target, target.initializer!)
            ..parent = target;
      _staticTypeContext = oldStaticTypeContext;
      if (shouldInline(target.initializer!)) {
        return evaluateAndTransformWithContext(node, node);
      }
    } else if (target is Procedure && target.kind == ProcedureKind.Method) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitStaticGet(node, removalSentinel);
  }

  @override
  TreeNode visitStaticTearOff(StaticTearOff node, TreeNode? removalSentinel) {
    final Member target = node.target;
    if (target is Procedure && target.kind == ProcedureKind.Method) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitStaticTearOff(node, removalSentinel);
  }

  @override
  TreeNode visitSwitchCase(SwitchCase node, TreeNode? removalSentinel) {
    transformExpressions(node.expressions, node);
    return super.visitSwitchCase(node, removalSentinel);
  }

  @override
  TreeNode visitSwitchStatement(
      SwitchStatement node, TreeNode? removalSentinel) {
    TreeNode result = super.visitSwitchStatement(node, removalSentinel);
    Library library = constantEvaluator.libraryOf(node);
    // ignore: unnecessary_null_comparison
    if (library != null && library.isNonNullableByDefault) {
      for (SwitchCase switchCase in node.cases) {
        for (Expression caseExpression in switchCase.expressions) {
          if (caseExpression is ConstantExpression) {
            if (!constantEvaluator.hasPrimitiveEqual(caseExpression.constant)) {
              constantEvaluator.errorReporter.report(
                  constantEvaluator.createLocatedMessage(
                      caseExpression,
                      templateConstEvalCaseImplementsEqual.withArguments(
                          caseExpression.constant,
                          constantEvaluator.isNonNullableByDefault)),
                  null);
            }
          } else {
            // If caseExpression is not ConstantExpression, an error is reported
            // elsewhere.
          }
        }
      }
    }
    return result;
  }

  @override
  TreeNode visitVariableGet(VariableGet node, TreeNode? removalSentinel) {
    final VariableDeclaration variable = node.variable;
    if (variable.isConst) {
      variable.initializer =
          evaluateAndTransformWithContext(variable, variable.initializer!)
            ..parent = variable;
      if (shouldInline(variable.initializer!)) {
        return evaluateAndTransformWithContext(node, node);
      }
    }
    return super.visitVariableGet(node, removalSentinel);
  }

  @override
  TreeNode visitListLiteral(ListLiteral node, TreeNode? removalSentinel) {
    if (node.isConst) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitListLiteral(node, removalSentinel);
  }

  @override
  TreeNode visitListConcatenation(
      ListConcatenation node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitSetLiteral(SetLiteral node, TreeNode? removalSentinel) {
    if (node.isConst) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitSetLiteral(node, removalSentinel);
  }

  @override
  TreeNode visitSetConcatenation(
      SetConcatenation node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitMapLiteral(MapLiteral node, TreeNode? removalSentinel) {
    if (node.isConst) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitMapLiteral(node, removalSentinel);
  }

  @override
  TreeNode visitTypeLiteral(TypeLiteral node, TreeNode? removalSentinel) {
    if (!containsFreeTypeVariables(node.type)) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitTypeLiteral(node, removalSentinel);
  }

  @override
  TreeNode visitMapConcatenation(
      MapConcatenation node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitConstructorInvocation(
      ConstructorInvocation node, TreeNode? removalSentinel) {
    if (node.isConst) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitConstructorInvocation(node, removalSentinel);
  }

  @override
  TreeNode visitStaticInvocation(
      StaticInvocation node, TreeNode? removalSentinel) {
    if (node.isConst) {
      return evaluateAndTransformWithContext(node, node);
    }
    return super.visitStaticInvocation(node, removalSentinel);
  }

  @override
  TreeNode visitConstantExpression(
      ConstantExpression node, TreeNode? removalSentinel) {
    Constant constant = node.constant;
    if (constant is UnevaluatedConstant) {
      Expression expression = constant.expression;
      return evaluateAndTransformWithContext(expression, expression);
    } else {
      node.constant = constantEvaluator.canonicalize(constant);
      return node;
    }
  }

  Expression evaluateAndTransformWithContext(
      TreeNode treeContext, Expression node) {
    return makeConstantExpression(evaluateWithContext(treeContext, node), node);
  }

  Constant evaluateWithContext(TreeNode treeContext, Expression node) {
    if (treeContext == node) {
      return constantEvaluator.evaluate(_staticTypeContext!, node);
    }

    return constantEvaluator.evaluate(_staticTypeContext!, node,
        contextNode: treeContext);
  }

  Expression makeConstantExpression(Constant constant, Expression node) {
    if (constant is UnevaluatedConstant &&
        constant.expression is InvalidExpression) {
      return constant.expression;
    }
    return new ConstantExpression(
        constant, node.getStaticType(_staticTypeContext!))
      ..fileOffset = node.fileOffset;
  }

  bool shouldInline(Expression initializer) {
    if (initializer is ConstantExpression) {
      return backend.shouldInlineConstant(initializer);
    }
    return true;
  }
}

class ConstantEvaluator implements ExpressionVisitor<Constant> {
  final ConstantsBackend backend;
  final NumberSemantics numberSemantics;
  late ConstantIntFolder intFolder;
  Map<String, String>? environmentDefines;
  final bool errorOnUnevaluatedConstant;
  final CoreTypes coreTypes;
  final TypeEnvironment typeEnvironment;
  StaticTypeContext? _staticTypeContext;
  final ErrorReporter errorReporter;
  final EvaluationMode evaluationMode;

  final bool enableTripleShift;
  final bool enableConstFunctions;

  final bool Function(DartType) isInstantiated =
      new IsInstantiatedVisitor().isInstantiated;

  final Map<Constant, Constant> canonicalizationCache;
  final Map<Node, Constant?> nodeCache;
  final CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();

  late Map<Class, bool> primitiveEqualCache;

  final NullConstant nullConstant = new NullConstant();
  final BoolConstant trueConstant = new BoolConstant(true);
  final BoolConstant falseConstant = new BoolConstant(false);

  InstanceBuilder? instanceBuilder;
  EvaluationEnvironment env;
  Set<Expression> replacementNodes = new Set<Expression>.identity();
  Map<Constant, Constant> lowered = new Map<Constant, Constant>.identity();

  bool seenUnevaluatedChild = false; // Any children that were left unevaluated?
  int lazyDepth = -1; // Current nesting depth of lazy regions.

  bool get shouldBeUnevaluated => seenUnevaluatedChild || lazyDepth != 0;

  bool get targetingJavaScript => numberSemantics == NumberSemantics.js;

  bool get isNonNullableByDefault =>
      _staticTypeContext!.nonNullable == Nullability.nonNullable;

  late ConstantWeakener _weakener;

  ConstantEvaluator(this.backend, this.environmentDefines, this.typeEnvironment,
      this.errorReporter,
      {this.enableTripleShift = false,
      this.enableConstFunctions = false,
      this.errorOnUnevaluatedConstant = false,
      this.evaluationMode: EvaluationMode.weak})
      : numberSemantics = backend.numberSemantics,
        coreTypes = typeEnvironment.coreTypes,
        canonicalizationCache = <Constant, Constant>{},
        nodeCache = <Node, Constant>{},
        env = new EvaluationEnvironment() {
    if (environmentDefines == null && !backend.supportsUnevaluatedConstants) {
      throw new ArgumentError(
          "No 'environmentDefines' passed to the constant evaluator but the "
          "ConstantsBackend does not support unevaluated constants.");
    }
    intFolder = new ConstantIntFolder.forSemantics(this, numberSemantics);
    primitiveEqualCache = <Class, bool>{
      coreTypes.boolClass: true,
      coreTypes.doubleClass: false,
      coreTypes.intClass: true,
      coreTypes.internalSymbolClass: true,
      coreTypes.listClass: true,
      coreTypes.mapClass: true,
      coreTypes.objectClass: true,
      coreTypes.setClass: true,
      coreTypes.stringClass: true,
      coreTypes.symbolClass: true,
      coreTypes.typeClass: true,
    };
    _weakener = new ConstantWeakener(this);
  }

  DartType convertType(DartType type) {
    switch (evaluationMode) {
      case EvaluationMode.strong:
      case EvaluationMode.agnostic:
        return norm(coreTypes, type);
      case EvaluationMode.weak:
        type = norm(coreTypes, type);
        return computeConstCanonicalType(type, coreTypes,
                isNonNullableByDefault: isNonNullableByDefault) ??
            type;
    }
  }

  List<DartType> convertTypes(List<DartType> types) {
    switch (evaluationMode) {
      case EvaluationMode.strong:
      case EvaluationMode.agnostic:
        return types.map((DartType type) => norm(coreTypes, type)).toList();
      case EvaluationMode.weak:
        return types.map((DartType type) {
          type = norm(coreTypes, type);
          return computeConstCanonicalType(type, coreTypes,
                  isNonNullableByDefault: isNonNullableByDefault) ??
              type;
        }).toList();
    }
  }

  LocatedMessage createLocatedMessage(TreeNode? node, Message message) {
    Uri? uri = getFileUri(node);
    if (uri == null) {
      // TODO(johnniwinther): Ensure that we always have a uri.
      return message.withoutLocation();
    }
    int offset = getFileOffset(uri, node);
    return message.withLocation(uri, offset, noLength);
  }

  // TODO(johnniwinther): Avoid this by adding a current file uri field.
  Uri? getFileUri(TreeNode? node) {
    while (node != null) {
      if (node is FileUriNode) {
        return node.fileUri;
      }
      node = node.parent;
    }
    return null;
  }

  int getFileOffset(Uri? uri, TreeNode? node) {
    if (uri == null) return TreeNode.noOffset;
    while (node != null && node.fileOffset == TreeNode.noOffset) {
      node = node.parent;
    }
    return node == null ? TreeNode.noOffset : node.fileOffset;
  }

  /// Evaluate [node] and possibly cache the evaluation result.
  /// Returns UnevaluatedConstant if the constant could not be evaluated.
  /// If the expression in the UnevaluatedConstant is an InvalidExpression,
  /// an error occurred during constant evaluation.
  Constant evaluate(StaticTypeContext context, Expression node,
      {TreeNode? contextNode}) {
    _staticTypeContext = context;
    seenUnevaluatedChild = false;
    lazyDepth = 0;
    Constant result = _evaluateSubexpression(node);
    if (result is AbortConstant) {
      if (result is _AbortDueToErrorConstant) {
        final LocatedMessage locatedMessageActualError =
            createLocatedMessage(result.node, result.message);
        final List<LocatedMessage> contextMessages = <LocatedMessage>[
          locatedMessageActualError
        ];
        if (result.context != null) contextMessages.addAll(result.context!);
        if (contextNode != null && contextNode != result.node) {
          contextMessages
              .add(createLocatedMessage(contextNode, messageConstEvalContext));
        }

        {
          final LocatedMessage locatedMessage =
              createLocatedMessage(node, messageConstEvalStartingPoint);
          errorReporter.report(locatedMessage, contextMessages);
        }
        return new UnevaluatedConstant(
            new InvalidExpression(result.message.message));
      }
      if (result is _AbortDueToInvalidExpressionConstant) {
        InvalidExpression invalid = new InvalidExpression(result.message)
          ..fileOffset = node.fileOffset;
        errorReporter.reportInvalidExpression(invalid);
        return new UnevaluatedConstant(invalid);
      } else if (result is _AbortDueToThrowConstant) {
        final Object value = result.throwValue;
        Message? message;
        if (value is Constant) {
          message = templateConstEvalUnhandledException.withArguments(
              value, isNonNullableByDefault);
        } else if (value is Error) {
          message = templateConstEvalUnhandledCoreException
              .withArguments(value.toString());
        }
        assert(message != null);

        final LocatedMessage locatedMessageActualError =
            createLocatedMessage(result.node, message!);
        final List<LocatedMessage> contextMessages = <LocatedMessage>[
          locatedMessageActualError
        ];
        {
          final LocatedMessage locatedMessage =
              createLocatedMessage(node, messageConstEvalStartingPoint);
          errorReporter.report(locatedMessage, contextMessages);
        }
        return new UnevaluatedConstant(new InvalidExpression(message.message));
      }
      throw "Unexpected error constant";
    }
    if (result is UnevaluatedConstant) {
      if (errorOnUnevaluatedConstant) {
        return createErrorConstant(node, messageConstEvalUnevaluated);
      }
      return canonicalize(new UnevaluatedConstant(
          removeRedundantFileUriExpressions(result.expression)));
    }
    return result;
  }

  /// Execute a function body using the [StatementConstantEvaluator].
  Constant executeBody(Statement statement) {
    StatementConstantEvaluator statementEvaluator =
        new StatementConstantEvaluator(this);
    ExecutionStatus status = statement.accept(statementEvaluator);
    if (status is ReturnStatus) {
      Constant? value = status.value;
      if (value == null) {
        // Void return type from executing the function body.
        return new NullConstant();
      }
      return value;
    } else if (status is AbortStatus) {
      return status.error;
    } else if (status is ProceedStatus) {
      // No return statement in function body with void return type.
      return new NullConstant();
    }
    return createInvalidExpressionConstant(statement,
        'No valid constant returned from the execution of $statement.');
  }

  /// Returns [null] on success and an error-"constant" on failure, as such the
  /// return value should be checked.
  AbortConstant? executeConstructorBody(Constructor constructor) {
    final Statement body = constructor.function.body!;
    StatementConstantEvaluator statementEvaluator =
        new StatementConstantEvaluator(this);
    ExecutionStatus status = body.accept(statementEvaluator);
    if (status is AbortStatus) {
      return status.error;
    } else if (status is ReturnStatus) {
      if (status.value == null) return null;
      // Should not be reachable.
      return createInvalidExpressionConstant(
          constructor, "Constructors can't have a return value.");
    } else if (status is! ProceedStatus) {
      return createInvalidExpressionConstant(
          constructor, "Invalid execution status of constructor body.");
    }
    return null;
  }

  /// Create an error-constant indicating that an error has been detected during
  /// constant evaluation.
  AbortConstant createErrorConstant(TreeNode node, Message message,
      {List<LocatedMessage>? context}) {
    return new _AbortDueToErrorConstant(node, message, context: context);
  }

  /// Create an error-constant indicating a construct that should not occur
  /// inside a potentially constant expression.
  /// It is assumed that an error has already been reported.
  AbortConstant createInvalidExpressionConstant(TreeNode node, String message) {
    return new _AbortDueToInvalidExpressionConstant(node, message);
  }

  /// Produce an unevaluated constant node for an expression.
  Constant unevaluated(Expression original, Expression replacement) {
    replacement.fileOffset = original.fileOffset;
    return new UnevaluatedConstant(
        new FileUriExpression(replacement, getFileUri(original)!)
          ..fileOffset = original.fileOffset);
  }

  Expression removeRedundantFileUriExpressions(Expression node) {
    return node.accept(new RedundantFileUriExpressionRemover()) as Expression;
  }

  /// Extract an expression from a (possibly unevaluated) constant to become
  /// part of the expression tree of another unevaluated constant.
  /// Makes sure a particular expression occurs only once in the tree by
  /// cloning further instances.
  Expression extract(Constant constant) {
    Expression expression = constant.asExpression();
    if (!replacementNodes.add(expression)) {
      expression = cloner.clone(expression);
      replacementNodes.add(expression);
    }
    return expression;
  }

  /// Enter a region of lazy evaluation. All leaf nodes are evaluated normally
  /// (to ensure inlining of referenced local variables), but composite nodes
  /// always treat their children as unevaluated, resulting in a partially
  /// evaluated clone of the original expression tree.
  /// Lazy evaluation is used for the subtrees of lazy operations with
  /// unevaluated conditions to ensure no errors are reported for problems
  /// in the subtree as long as the subtree is potentially constant.
  void enterLazy() => lazyDepth++;

  /// Leave a (possibly nested) region of lazy evaluation.
  void leaveLazy() => lazyDepth--;

  Constant lower(Constant original, Constant replacement) {
    if (!identical(original, replacement)) {
      original = canonicalize(original);
      replacement = canonicalize(replacement);
      lowered[replacement] = original;
      return replacement;
    }
    return canonicalize(replacement);
  }

  Constant unlower(Constant constant) {
    return lowered[constant] ?? constant;
  }

  Constant lowerListConstant(ListConstant constant) {
    if (shouldBeUnevaluated) return constant;
    return lower(constant, backend.lowerListConstant(constant));
  }

  Constant lowerSetConstant(SetConstant constant) {
    if (shouldBeUnevaluated) return constant;
    return lower(constant, backend.lowerSetConstant(constant));
  }

  Constant lowerMapConstant(MapConstant constant) {
    if (shouldBeUnevaluated) return constant;
    return lower(constant, backend.lowerMapConstant(constant));
  }

  Map<Uri, Set<Reference>> _constructorCoverage = {};

  ConstantCoverage getConstantCoverage() {
    return new ConstantCoverage(_constructorCoverage);
  }

  void _recordConstructorCoverage(Constructor constructor, TreeNode caller) {
    Uri currentUri = getFileUri(caller)!;
    Set<Reference> uriCoverage = _constructorCoverage[currentUri] ??= {};
    uriCoverage.add(constructor.reference);
  }

  /// Evaluate [node] and possibly cache the evaluation result.
  ///
  /// Returns [_AbortDueToErrorConstant] or
  /// [_AbortDueToInvalidExpressionConstant] (both of which is an
  /// [AbortConstant]) if the expression can't be evaluated.
  /// As such the return value should be checked (e.g. `is AbortConstant`)
  /// before further use.
  Constant _evaluateSubexpression(Expression node) {
    if (node is ConstantExpression) {
      if (node.constant is! UnevaluatedConstant) {
        // ConstantExpressions just pointing to an actual constant can be
        // short-circuited. Note that it's accepted instead of just returned to
        // get canonicalization.
        return node.accept(this);
      }
    } else if (node is BasicLiteral) {
      // Basic literals (string literals, int literals, double literals,
      // bool literals and null literals) can be short-circuited too.
      return node.accept(this);
    }

    bool wasUnevaluated = seenUnevaluatedChild;
    seenUnevaluatedChild = false;
    Constant result;
    if (env.isEmpty) {
      // We only try to evaluate the same [node] *once* within an empty
      // environment.
      // For const functions, recompute getters instead of using the cached
      // value.
      bool isGetter = node is InstanceGet || node is PropertyGet;
      if (nodeCache.containsKey(node) && !(enableConstFunctions && isGetter)) {
        Constant? cachedResult = nodeCache[node];
        if (cachedResult == null) {
          // [null] is a sentinel value only used when still evaluating the same
          // node.
          return createErrorConstant(node, messageConstEvalCircularity);
        }
        result = cachedResult;
      } else {
        nodeCache[node] = null;
        Constant evaluatedResult = node.accept(this);
        if (evaluatedResult is AbortConstant) {
          nodeCache.remove(node);
          return evaluatedResult;
        } else {
          nodeCache[node] = evaluatedResult;
        }
        result = evaluatedResult;
      }
    } else {
      bool sentinelInserted = false;
      if (nodeCache.containsKey(node)) {
        bool isRecursiveFunctionCall = node is MethodInvocation ||
            node is InstanceInvocation ||
            node is FunctionInvocation ||
            node is LocalFunctionInvocation ||
            node is StaticInvocation;
        if (nodeCache[node] == null &&
            !(enableConstFunctions && isRecursiveFunctionCall)) {
          // recursive call
          return createErrorConstant(node, messageConstEvalCircularity);
        }
        // else we've seen the node before and come to a result -> we won't
        // go into an infinite loop here either.
      } else {
        // We haven't seen this node before. Risk of loop.
        nodeCache[node] = null;
        sentinelInserted = true;
      }
      Constant evaluatedResult = node.accept(this);
      if (sentinelInserted) {
        nodeCache.remove(node);
      }
      if (evaluatedResult is AbortConstant) {
        return evaluatedResult;
      }
      result = evaluatedResult;
    }
    seenUnevaluatedChild = wasUnevaluated || result is UnevaluatedConstant;
    return result;
  }

  Constant _evaluateNullableSubexpression(Expression? node) {
    if (node == null) return nullConstant;
    return _evaluateSubexpression(node);
  }

  @override
  Constant defaultExpression(Expression node) {
    // Only a subset of the expression language is valid for constant
    // evaluation.
    return createInvalidExpressionConstant(
        node, 'Constant evaluation has no support for ${node.runtimeType}!');
  }

  @override
  Constant visitFileUriExpression(FileUriExpression node) {
    return _evaluateSubexpression(node.expression);
  }

  @override
  Constant visitNullLiteral(NullLiteral node) => nullConstant;

  @override
  Constant visitBoolLiteral(BoolLiteral node) {
    return makeBoolConstant(node.value);
  }

  @override
  Constant visitIntLiteral(IntLiteral node) {
    // The frontend ensures that integer literals are valid according to the
    // target representation.
    return canonicalize(intFolder.makeIntConstant(node.value, unsigned: true));
  }

  @override
  Constant visitDoubleLiteral(DoubleLiteral node) {
    return canonicalize(new DoubleConstant(node.value));
  }

  @override
  Constant visitStringLiteral(StringLiteral node) {
    return canonicalize(new StringConstant(node.value));
  }

  @override
  Constant visitTypeLiteral(TypeLiteral node) {
    DartType? type = _evaluateDartType(node, node.type);
    if (type != null) {
      type = convertType(type);
    }
    if (type == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(type != null);
    return canonicalize(new TypeLiteralConstant(type));
  }

  @override
  Constant visitConstantExpression(ConstantExpression node) {
    Constant constant = node.constant;
    Constant result = constant;
    if (constant is UnevaluatedConstant) {
      if (environmentDefines != null) {
        result = _evaluateSubexpression(constant.expression);
        if (result is AbortConstant) return result;
      } else {
        // Still no environment. Doing anything is just wasted time.
        result = constant;
      }
    }
    // If there were already constants in the AST then we make sure we
    // re-canonicalize them.  After running the transformer we will therefore
    // have a fully-canonicalized constant DAG with roots coming from the
    // [ConstantExpression] nodes in the AST.
    return canonicalize(result);
  }

  @override
  Constant visitListLiteral(ListLiteral node) {
    if (!node.isConst && !enableConstFunctions) {
      return createInvalidExpressionConstant(node, "Non-constant list literal");
    }
    final ListConstantBuilder builder = new ListConstantBuilder(
        node, convertType(node.typeArgument), this,
        isMutable: !node.isConst);
    // These expressions are at the same level, so one of them being
    // unevaluated doesn't mean a sibling is or has an unevaluated child.
    // We therefore reset it before each call, combine it and set it correctly
    // at the end.
    bool wasOrBecameUnevaluated = seenUnevaluatedChild;
    for (Expression element in node.expressions) {
      seenUnevaluatedChild = false;
      AbortConstant? error = builder.add(element);
      wasOrBecameUnevaluated |= seenUnevaluatedChild;
      if (error != null) return error;
    }
    seenUnevaluatedChild = wasOrBecameUnevaluated;
    return builder.build();
  }

  @override
  Constant visitListConcatenation(ListConcatenation node) {
    final ListConstantBuilder builder =
        new ListConstantBuilder(node, convertType(node.typeArgument), this);
    for (Expression list in node.lists) {
      AbortConstant? error = builder.addSpread(list);
      if (error != null) return error;
    }
    return builder.build();
  }

  @override
  Constant visitSetLiteral(SetLiteral node) {
    if (!node.isConst) {
      return createInvalidExpressionConstant(node, "Non-constant set literal");
    }
    final SetConstantBuilder builder =
        new SetConstantBuilder(node, convertType(node.typeArgument), this);
    // These expressions are at the same level, so one of them being
    // unevaluated doesn't mean a sibling is or has an unevaluated child.
    // We therefore reset it before each call, combine it and set it correctly
    // at the end.
    bool wasOrBecameUnevaluated = seenUnevaluatedChild;
    for (Expression element in node.expressions) {
      seenUnevaluatedChild = false;
      AbortConstant? error = builder.add(element);
      wasOrBecameUnevaluated |= seenUnevaluatedChild;
      if (error != null) return error;
    }
    seenUnevaluatedChild = wasOrBecameUnevaluated;
    return builder.build();
  }

  @override
  Constant visitSetConcatenation(SetConcatenation node) {
    final SetConstantBuilder builder =
        new SetConstantBuilder(node, convertType(node.typeArgument), this);
    for (Expression set_ in node.sets) {
      AbortConstant? error = builder.addSpread(set_);
      if (error != null) return error;
    }
    return builder.build();
  }

  @override
  Constant visitMapLiteral(MapLiteral node) {
    if (!node.isConst) {
      return createInvalidExpressionConstant(node, "Non-constant map literal");
    }
    final MapConstantBuilder builder = new MapConstantBuilder(
        node, convertType(node.keyType), convertType(node.valueType), this);
    // These expressions are at the same level, so one of them being
    // unevaluated doesn't mean a sibling is or has an unevaluated child.
    // We therefore reset it before each call, combine it and set it correctly
    // at the end.
    bool wasOrBecameUnevaluated = seenUnevaluatedChild;
    for (MapLiteralEntry element in node.entries) {
      seenUnevaluatedChild = false;
      AbortConstant? error = builder.add(element);
      wasOrBecameUnevaluated |= seenUnevaluatedChild;
      if (error != null) return error;
    }
    seenUnevaluatedChild = wasOrBecameUnevaluated;
    return builder.build();
  }

  @override
  Constant visitMapConcatenation(MapConcatenation node) {
    final MapConstantBuilder builder = new MapConstantBuilder(
        node, convertType(node.keyType), convertType(node.valueType), this);
    for (Expression map in node.maps) {
      AbortConstant? error = builder.addSpread(map);
      if (error != null) return error;
    }
    return builder.build();
  }

  @override
  Constant visitFunctionExpression(FunctionExpression node) {
    if (enableConstFunctions) {
      return new FunctionValue(node.function, env);
    }
    return createInvalidExpressionConstant(node, "Function literal");
  }

  @override
  Constant visitConstructorInvocation(ConstructorInvocation node) {
    if (!node.isConst && !enableConstFunctions) {
      return createInvalidExpressionConstant(
          node, 'Non-constant constructor invocation "$node".');
    }

    final Constructor constructor = node.target;
    AbortConstant? error = checkConstructorConst(node, constructor);
    if (error != null) return error;

    final Class klass = constructor.enclosingClass;
    if (klass.isAbstract) {
      // Probably unreachable.
      return createInvalidExpressionConstant(
          node, 'Constructor "$node" belongs to abstract class "${klass}".');
    }

    final List<Constant>? positionals =
        _evaluatePositionalArguments(node.arguments);
    if (positionals == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(positionals != null);

    final Map<String, Constant>? named =
        _evaluateNamedArguments(node.arguments);
    if (named == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(named != null);

    bool isSymbol = klass == coreTypes.internalSymbolClass;
    if (isSymbol && shouldBeUnevaluated) {
      return unevaluated(
          node,
          new ConstructorInvocation(constructor,
              unevaluatedArguments(positionals, named, node.arguments.types),
              isConst: true));
    }

    // Special case the dart:core's Symbol class here and convert it to a
    // [SymbolConstant].  For invalid values we report a compile-time error.
    if (isSymbol) {
      final Constant nameValue = positionals.single;

      if (nameValue is StringConstant && isValidSymbolName(nameValue.value)) {
        return canonicalize(new SymbolConstant(nameValue.value, null));
      }
      return createErrorConstant(
          node.arguments.positional.first,
          templateConstEvalInvalidSymbolName.withArguments(
              nameValue, isNonNullableByDefault));
    }

    List<DartType>? types = _evaluateTypeArguments(node, node.arguments);
    if (types == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(types != null);

    final List<DartType> typeArguments = convertTypes(types);

    // Fill in any missing type arguments with "dynamic".
    for (int i = typeArguments.length; i < klass.typeParameters.length; i++) {
      // Probably unreachable.
      typeArguments.add(const DynamicType());
    }

    // Start building a new instance.
    return withNewInstanceBuilder(klass, typeArguments, () {
      // "Run" the constructor (and any super constructor calls), which will
      // initialize the fields of the new instance.
      if (shouldBeUnevaluated) {
        enterLazy();
        AbortConstant? error = handleConstructorInvocation(
            constructor, typeArguments, positionals, named, node);
        if (error != null) return error;
        leaveLazy();
        return unevaluated(node, instanceBuilder!.buildUnevaluatedInstance());
      }
      AbortConstant? error = handleConstructorInvocation(
          constructor, typeArguments, positionals, named, node);
      if (error != null) return error;
      if (shouldBeUnevaluated) {
        return unevaluated(node, instanceBuilder!.buildUnevaluatedInstance());
      }
      return canonicalize(instanceBuilder!.buildInstance());
    });
  }

  /// Returns [null] on success and an error-"constant" on failure, as such the
  /// return value should be checked.
  AbortConstant? checkConstructorConst(TreeNode node, Constructor constructor) {
    if (!constructor.isConst) {
      return createInvalidExpressionConstant(
          node, 'Non-const constructor invocation.');
    }
    if (constructor.function.body != null &&
        constructor.function.body is! EmptyStatement &&
        !enableConstFunctions) {
      // Probably unreachable.
      return createInvalidExpressionConstant(
          node,
          'Constructor "$node" has non-trivial body '
          '"${constructor.function.body.runtimeType}".');
    }
    return null;
  }

  @override
  Constant visitInstanceCreation(InstanceCreation node) {
    return withNewInstanceBuilder(
        node.classNode, convertTypes(node.typeArguments), () {
      for (AssertStatement statement in node.asserts) {
        AbortConstant? error = checkAssert(statement);
        if (error != null) return error;
      }
      AbortConstant? error;
      for (MapEntry<Reference, Expression> entry in node.fieldValues.entries) {
        Reference fieldRef = entry.key;
        Expression value = entry.value;
        Constant constant = _evaluateSubexpression(value);
        if (constant is AbortConstant) {
          error = constant;
          break;
        }
        instanceBuilder!.setFieldValue(fieldRef.asField, constant);
      }
      if (error != null) return error;
      for (Expression value in node.unusedArguments) {
        if (error != null) return error;
        Constant constant = _evaluateSubexpression(value);
        if (constant is AbortConstant) {
          error ??= constant;
          return error;
        }
        if (constant is UnevaluatedConstant) {
          instanceBuilder!.unusedArguments.add(extract(constant));
        }
      }
      if (error != null) return error;
      if (shouldBeUnevaluated) {
        return unevaluated(node, instanceBuilder!.buildUnevaluatedInstance());
      }
      // We can get here when re-evaluating a previously unevaluated constant.
      return canonicalize(instanceBuilder!.buildInstance());
    });
  }

  bool isValidSymbolName(String name) {
    // See https://api.dartlang.org/stable/2.0.0/dart-core/Symbol/Symbol.html:
    //
    //  A qualified name is a valid name preceded by a public identifier name
    //  and a '.', e.g., foo.bar.baz= is a qualified version of baz=.
    //
    //  That means that the content of the name String must be either
    //     - a valid public Dart identifier (that is, an identifier not
    //       starting with "_"),
    //     - such an identifier followed by "=" (a setter name),
    //     - the name of a declarable operator,
    //     - any of the above preceded by any number of qualifiers, where a
    //       qualifier is a non-private identifier followed by '.',
    //     - or the empty string (the default name of a library with no library
    //       name declaration).

    const Set<String> operatorNames = const <String>{
      '+',
      '-',
      '*',
      '/',
      '%',
      '~/',
      '&',
      '|',
      '^',
      '~',
      '<<',
      '>>',
      '>>>',
      '<',
      '<=',
      '>',
      '>=',
      '==',
      '[]',
      '[]=',
      'unary-'
    };

    // ignore: unnecessary_null_comparison
    if (name == null) return false;
    if (name == '') return true;

    final List<String> parts = name.split('.');

    // Each qualifier must be a public identifier.
    for (int i = 0; i < parts.length - 1; ++i) {
      if (!isValidPublicIdentifier(parts[i])) return false;
    }

    String last = parts.last;
    if (operatorNames.contains(last)) {
      return enableTripleShift || last != '>>>';
    }
    if (last.endsWith('=')) {
      last = last.substring(0, last.length - 1);
    }
    if (!isValidPublicIdentifier(last)) return false;

    return true;
  }

  /// From the Dart Language specification:
  ///
  ///   IDENTIFIER:
  ///     IDENTIFIER_START IDENTIFIER_PART*
  ///
  ///   IDENTIFIER_START:
  ///       IDENTIFIER_START_NO_DOLLAR | ‘$’
  ///
  ///   IDENTIFIER_PART:
  ///       IDENTIFIER_START | DIGIT
  ///
  ///   IDENTIFIER_NO_DOLLAR:
  ///     IDENTIFIER_START_NO_DOLLAR IDENTIFIER_PART_NO_DOLLAR*
  ///
  ///   IDENTIFIER_START_NO_DOLLAR:
  ///       LETTER | '_'
  ///
  ///   IDENTIFIER_PART_NO_DOLLAR:
  ///       IDENTIFIER_START_NO_DOLLAR | DIGIT
  ///
  static final RegExp publicIdentifierRegExp =
      new RegExp(r'^[a-zA-Z$][a-zA-Z0-9_$]*$');

  static const Set<String> nonUsableKeywords = const <String>{
    'assert',
    'break',
    'case',
    'catch',
    'class',
    'const',
    'continue',
    'default',
    'do',
    'else',
    'enum',
    'extends',
    'false',
    'final',
    'finally',
    'for',
    'if',
    'in',
    'is',
    'new',
    'null',
    'rethrow',
    'return',
    'super',
    'switch',
    'this',
    'throw',
    'true',
    'try',
    'var',
    'while',
    'with',
  };

  bool isValidPublicIdentifier(String name) {
    return publicIdentifierRegExp.hasMatch(name) &&
        !nonUsableKeywords.contains(name);
  }

  /// Returns [null] on success and an error-"constant" on failure, as such the
  /// return value should be checked.
  AbortConstant? handleConstructorInvocation(
      Constructor constructor,
      List<DartType> typeArguments,
      List<Constant> positionalArguments,
      Map<String, Constant> namedArguments,
      TreeNode caller) {
    return withNewEnvironment(() {
      final Class klass = constructor.enclosingClass;
      final FunctionNode function = constructor.function;

      // Mark in file of the caller that we evaluate this specific constructor.
      _recordConstructorCoverage(constructor, caller);

      // We simulate now the constructor invocation.

      // Step 1) Map type arguments and normal arguments from caller to
      //         callee.
      for (int i = 0; i < klass.typeParameters.length; i++) {
        env.addTypeParameterValue(klass.typeParameters[i], typeArguments[i]);
      }
      for (int i = 0; i < function.positionalParameters.length; i++) {
        final VariableDeclaration parameter = function.positionalParameters[i];
        final Constant value = (i < positionalArguments.length)
            ? positionalArguments[i]
            // TODO(johnniwinther): This should call [_evaluateSubexpression].
            : _evaluateNullableSubexpression(parameter.initializer);
        if (value is AbortConstant) return value;
        env.addVariableValue(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);
      }

      // Step 2) Run all initializers (including super calls) with environment
      //         setup.
      for (final Field field in klass.fields) {
        if (!field.isStatic) {
          Constant constant = _evaluateNullableSubexpression(field.initializer);
          if (constant is AbortConstant) return constant;
          instanceBuilder!.setFieldValue(field, constant);
        }
      }
      for (final Initializer init in constructor.initializers) {
        if (init is FieldInitializer) {
          Constant constant = _evaluateSubexpression(init.value);
          if (constant is AbortConstant) return constant;
          instanceBuilder!.setFieldValue(init.field, constant);
        } else if (init is LocalInitializer) {
          final VariableDeclaration variable = init.variable;
          Constant constant = _evaluateSubexpression(variable.initializer!);
          if (constant is AbortConstant) return constant;
          env.addVariableValue(variable, constant);
        } else if (init is SuperInitializer) {
          AbortConstant? error = checkConstructorConst(init, constructor);
          if (error != null) return error;
          List<DartType>? types = _evaluateSuperTypeArguments(
              init, constructor.enclosingClass.supertype!);
          if (types == null) {
            AbortConstant error = _gotError!;
            _gotError = null;
            return error;
          }
          assert(_gotError == null);
          // ignore: unnecessary_null_comparison
          assert(types != null);

          List<Constant>? positionalArguments =
              _evaluatePositionalArguments(init.arguments);
          if (positionalArguments == null) {
            AbortConstant error = _gotError!;
            _gotError = null;
            return error;
          }
          assert(_gotError == null);
          // ignore: unnecessary_null_comparison
          assert(positionalArguments != null);
          Map<String, Constant>? namedArguments =
              _evaluateNamedArguments(init.arguments);
          if (namedArguments == null) {
            AbortConstant error = _gotError!;
            _gotError = null;
            return error;
          }
          assert(_gotError == null);
          // ignore: unnecessary_null_comparison
          assert(namedArguments != null);
          error = handleConstructorInvocation(init.target, types,
              positionalArguments, namedArguments, constructor);
          if (error != null) return error;
        } else if (init is RedirectingInitializer) {
          // Since a redirecting constructor targets a constructor of the same
          // class, we pass the same [typeArguments].
          AbortConstant? error = checkConstructorConst(init, constructor);
          if (error != null) return error;
          List<Constant>? positionalArguments =
              _evaluatePositionalArguments(init.arguments);
          if (positionalArguments == null) {
            AbortConstant error = _gotError!;
            _gotError = null;
            return error;
          }
          assert(_gotError == null);
          // ignore: unnecessary_null_comparison
          assert(positionalArguments != null);

          Map<String, Constant>? namedArguments =
              _evaluateNamedArguments(init.arguments);
          if (namedArguments == null) {
            AbortConstant error = _gotError!;
            _gotError = null;
            return error;
          }
          assert(_gotError == null);
          // ignore: unnecessary_null_comparison
          assert(namedArguments != null);

          error = handleConstructorInvocation(init.target, typeArguments,
              positionalArguments, namedArguments, constructor);
          if (error != null) return error;
        } else if (init is AssertInitializer) {
          AbortConstant? error = checkAssert(init.statement);
          if (error != null) return error;
        } else {
          // InvalidInitializer or new Initializers.
          // Probably unreachable. InvalidInitializer is (currently) only
          // created for classes with no constructors that doesn't have a
          // super that takes no arguments. It thus cannot be const.
          // Explicit constructors with incorrect super calls will get a
          // ShadowInvalidInitializer which is actually a LocalInitializer.
          return createInvalidExpressionConstant(
              constructor,
              'No support for handling initializer of type '
              '"${init.runtimeType}".');
        }
      }

      for (UnevaluatedConstant constant in env.unevaluatedUnreadConstants) {
        instanceBuilder!.unusedArguments.add(extract(constant));
      }

      // ignore: unnecessary_null_comparison
      if (enableConstFunctions && constructor.function != null) {
        AbortConstant? error = executeConstructorBody(constructor);
        if (error != null) return error;
      }

      return null;
    });
  }

  /// Returns [null] on success and an error-"constant" on failure, as such the
  /// return value should be checked.
  AbortConstant? checkAssert(AssertStatement statement) {
    final Constant condition = _evaluateSubexpression(statement.condition);
    if (condition is AbortConstant) return condition;

    if (shouldBeUnevaluated) {
      Expression? message = null;
      if (statement.message != null) {
        enterLazy();
        Constant constant = _evaluateSubexpression(statement.message!);
        if (constant is AbortConstant) return constant;
        message = extract(constant);
        leaveLazy();
      }
      instanceBuilder!.asserts.add(new AssertStatement(extract(condition),
          message: message,
          conditionStartOffset: statement.conditionStartOffset,
          conditionEndOffset: statement.conditionEndOffset));
    } else if (condition is BoolConstant) {
      if (!condition.value) {
        if (statement.message == null) {
          return createErrorConstant(
              statement.condition, messageConstEvalFailedAssertion);
        }
        final Constant message = _evaluateSubexpression(statement.message!);
        if (message is AbortConstant) return message;
        if (shouldBeUnevaluated) {
          instanceBuilder!.asserts.add(new AssertStatement(extract(condition),
              message: extract(message),
              conditionStartOffset: statement.conditionStartOffset,
              conditionEndOffset: statement.conditionEndOffset));
        } else if (message is StringConstant) {
          return createErrorConstant(
              statement.condition,
              templateConstEvalFailedAssertionWithMessage
                  .withArguments(message.value));
        } else {
          return createErrorConstant(
              statement.message!,
              templateConstEvalInvalidType.withArguments(
                  message,
                  typeEnvironment.coreTypes.stringLegacyRawType,
                  message.getType(_staticTypeContext!),
                  isNonNullableByDefault));
        }
      }
    } else {
      return createErrorConstant(
          statement.condition,
          templateConstEvalInvalidType.withArguments(
              condition,
              typeEnvironment.coreTypes.boolLegacyRawType,
              condition.getType(_staticTypeContext!),
              isNonNullableByDefault));
    }

    return null;
  }

  @override
  Constant visitInvalidExpression(InvalidExpression node) {
    return createInvalidExpressionConstant(node, node.message ?? '');
  }

  @override
  Constant visitDynamicInvocation(DynamicInvocation node) {
    // We have no support for generic method invocation at the moment.
    if (node.arguments.types.isNotEmpty) {
      return createInvalidExpressionConstant(node, "generic method invocation");
    }

    // We have no support for method invocation with named arguments at the
    // moment.
    if (node.arguments.named.isNotEmpty) {
      return createInvalidExpressionConstant(
          node, "method invocation with named arguments");
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    final List<Constant>? positionalArguments =
        _evaluatePositionalArguments(node.arguments);

    if (positionalArguments == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(positionalArguments != null);

    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new DynamicInvocation(
              node.kind,
              extract(receiver),
              node.name,
              unevaluatedArguments(
                  positionalArguments, {}, node.arguments.types))
            ..fileOffset = node.fileOffset);
    }

    return _handleInvocation(node, node.name, receiver, positionalArguments,
        arguments: node.arguments);
  }

  @override
  Constant visitInstanceInvocation(InstanceInvocation node) {
    // We have no support for generic method invocation at the moment.
    if (node.arguments.types.isNotEmpty) {
      return createInvalidExpressionConstant(node, "generic method invocation");
    }

    // We have no support for method invocation with named arguments at the
    // moment.
    if (node.arguments.named.isNotEmpty) {
      return createInvalidExpressionConstant(
          node, "method invocation with named arguments");
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    final List<Constant>? positionalArguments =
        _evaluatePositionalArguments(node.arguments);

    if (positionalArguments == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(positionalArguments != null);

    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new InstanceInvocation(
              node.kind,
              extract(receiver),
              node.name,
              unevaluatedArguments(
                  positionalArguments, {}, node.arguments.types),
              functionType: node.functionType,
              interfaceTarget: node.interfaceTarget)
            ..fileOffset = node.fileOffset
            ..flags = node.flags);
    }

    return _handleInvocation(node, node.name, receiver, positionalArguments,
        arguments: node.arguments);
  }

  @override
  Constant visitFunctionInvocation(FunctionInvocation node) {
    if (!enableConstFunctions) {
      return createInvalidExpressionConstant(node, "function invocation");
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;

    return _evaluateFunctionInvocation(node, receiver, node.arguments);
  }

  @override
  Constant visitLocalFunctionInvocation(LocalFunctionInvocation node) {
    if (!enableConstFunctions) {
      return createInvalidExpressionConstant(node, "local function invocation");
    }

    final Constant receiver = env.lookupVariable(node.variable)!;
    // ignore: unnecessary_null_comparison
    assert(receiver != null);
    if (receiver is AbortConstant) return receiver;

    return _evaluateFunctionInvocation(node, receiver, node.arguments);
  }

  Constant _evaluateFunctionInvocation(
      TreeNode node, Constant receiver, Arguments argumentsNode) {
    final List<Constant>? arguments =
        _evaluatePositionalArguments(argumentsNode);

    if (arguments == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(arguments != null);

    // Evaluate type arguments of the function invoked.
    List<DartType>? types = _evaluateTypeArguments(node, argumentsNode);
    if (types == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(types != null);

    // Evaluate named arguments of the function invoked.
    final Map<String, Constant>? named = _evaluateNamedArguments(argumentsNode);
    if (named == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(named != null);

    if (receiver is FunctionValue) {
      return _handleFunctionInvocation(
          receiver.function, types, arguments, named,
          functionEnvironment: receiver.environment);
    } else {
      return createInvalidExpressionConstant(
          node, "function invocation with invalid receiver");
    }
  }

  @override
  Constant visitEqualsCall(EqualsCall node) {
    final Constant left = _evaluateSubexpression(node.left);
    if (left is AbortConstant) return left;
    final Constant right = _evaluateSubexpression(node.right);
    if (right is AbortConstant) return right;

    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new EqualsCall(extract(left), extract(right),
              functionType: node.functionType,
              interfaceTarget: node.interfaceTarget)
            ..fileOffset = node.fileOffset);
    }

    return _handleEquals(node, left, right);
  }

  @override
  Constant visitEqualsNull(EqualsNull node) {
    final Constant expression = _evaluateSubexpression(node.expression);
    if (expression is AbortConstant) return expression;

    if (shouldBeUnevaluated) {
      return unevaluated(node,
          new EqualsNull(extract(expression))..fileOffset = node.fileOffset);
    }

    return _handleEquals(node, expression, nullConstant);
  }

  Constant _handleEquals(Expression node, Constant left, Constant right) {
    if (left is NullConstant ||
        left is BoolConstant ||
        left is IntConstant ||
        left is DoubleConstant ||
        left is StringConstant ||
        right is NullConstant) {
      // [DoubleConstant] uses [identical] to determine equality, so we need
      // to take the special cases into account.
      return doubleSpecialCases(left, right) ?? makeBoolConstant(left == right);
    } else {
      return createErrorConstant(
          node,
          templateConstEvalInvalidEqualsOperandType.withArguments(
              left, left.getType(_staticTypeContext!), isNonNullableByDefault));
    }
  }

  Constant _handleInvocation(Expression node, Name name, Constant receiver,
      List<Constant> positionalArguments,
      {required Arguments arguments}) {
    final String op = name.text;

    // TODO(kallentu): Handle all constant toString methods.
    if (receiver is PrimitiveConstant &&
        op == 'toString' &&
        enableConstFunctions) {
      return new StringConstant(receiver.value.toString());
    }

    // Handle == and != first (it's common between all types). Since `a != b` is
    // parsed as `!(a == b)` it is handled implicitly through ==.
    if (positionalArguments.length == 1 && op == '==') {
      final Constant right = positionalArguments[0];
      return _handleEquals(node, receiver, right);
    }

    // This is a white-listed set of methods we need to support on constants.
    if (receiver is StringConstant) {
      if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];
        switch (op) {
          case '+':
            if (other is StringConstant) {
              return canonicalize(
                  new StringConstant(receiver.value + other.value));
            }
            return createErrorConstant(
                node,
                templateConstEvalInvalidBinaryOperandType.withArguments(
                    '+',
                    receiver,
                    typeEnvironment.coreTypes.stringLegacyRawType,
                    other.getType(_staticTypeContext!),
                    isNonNullableByDefault));
          case '[]':
            if (enableConstFunctions) {
              int? index = intFolder.asInt(other);
              if (index != null) {
                if (index < 0 || index >= receiver.value.length) {
                  return new _AbortDueToThrowConstant(
                      node, new RangeError.index(index, receiver.value));
                }
                return canonicalize(new StringConstant(receiver.value[index]));
              }
              return createErrorConstant(
                  node,
                  templateConstEvalInvalidBinaryOperandType.withArguments(
                      '[]',
                      receiver,
                      typeEnvironment.coreTypes.intNonNullableRawType,
                      other.getType(_staticTypeContext!),
                      isNonNullableByDefault));
            }
        }
      }
    } else if (intFolder.isInt(receiver)) {
      if (positionalArguments.length == 0) {
        return canonicalize(intFolder.foldUnaryOperator(node, op, receiver));
      } else if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];
        if (intFolder.isInt(other)) {
          return canonicalize(
              intFolder.foldBinaryOperator(node, op, receiver, other));
        } else if (other is DoubleConstant) {
          if ((op == '|' || op == '&' || op == '^') ||
              (op == '<<' || op == '>>' || op == '>>>')) {
            return createErrorConstant(
                node,
                templateConstEvalInvalidBinaryOperandType.withArguments(
                    op,
                    other,
                    typeEnvironment.coreTypes.intLegacyRawType,
                    other.getType(_staticTypeContext!),
                    isNonNullableByDefault));
          }
          num receiverValue = (receiver as PrimitiveConstant<num>).value;
          return canonicalize(evaluateBinaryNumericOperation(
              op, receiverValue, other.value, node));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidBinaryOperandType.withArguments(
                op,
                receiver,
                typeEnvironment.coreTypes.numLegacyRawType,
                other.getType(_staticTypeContext!),
                isNonNullableByDefault));
      }
    } else if (receiver is DoubleConstant) {
      if ((op == '|' || op == '&' || op == '^') ||
          (op == '<<' || op == '>>' || op == '>>>')) {
        return createErrorConstant(
            node,
            templateConstEvalInvalidBinaryOperandType.withArguments(
                op,
                receiver,
                typeEnvironment.coreTypes.intLegacyRawType,
                receiver.getType(_staticTypeContext!),
                isNonNullableByDefault));
      }
      if (positionalArguments.length == 0) {
        switch (op) {
          case 'unary-':
            return canonicalize(new DoubleConstant(-receiver.value));
        }
      } else if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];

        if (other is IntConstant || other is DoubleConstant) {
          final num value = (other as PrimitiveConstant<num>).value;
          return canonicalize(
              evaluateBinaryNumericOperation(op, receiver.value, value, node));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidBinaryOperandType.withArguments(
                op,
                receiver,
                typeEnvironment.coreTypes.numLegacyRawType,
                other.getType(_staticTypeContext!),
                isNonNullableByDefault));
      }
    } else if (receiver is BoolConstant) {
      if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];
        if (other is BoolConstant) {
          switch (op) {
            case '|':
              return canonicalize(
                  new BoolConstant(receiver.value || other.value));
            case '&':
              return canonicalize(
                  new BoolConstant(receiver.value && other.value));
            case '^':
              return canonicalize(
                  new BoolConstant(receiver.value != other.value));
          }
        }
      }
    } else if (receiver is NullConstant) {
      return createErrorConstant(node, messageConstEvalNullValue);
    } else if (receiver is ListConstant && enableConstFunctions) {
      if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];
        switch (op) {
          case '[]':
            int? index = intFolder.asInt(other);
            if (index != null) {
              if (index < 0 || index >= receiver.entries.length) {
                return new _AbortDueToThrowConstant(
                    node, new RangeError.index(index, receiver.entries));
              }
              return receiver.entries[index];
            }
            return createErrorConstant(
                node,
                templateConstEvalInvalidBinaryOperandType.withArguments(
                    '[]',
                    receiver,
                    typeEnvironment.coreTypes.intNonNullableRawType,
                    other.getType(_staticTypeContext!),
                    isNonNullableByDefault));
          case 'add':
            if (receiver is MutableListConstant) {
              receiver.entries.add(other);
              return receiver;
            }
            return new _AbortDueToThrowConstant(node, new UnsupportedError(op));
        }
      }
    } else if (receiver is MapConstant && enableConstFunctions) {
      if (positionalArguments.length == 1) {
        final Constant other = positionalArguments[0];
        switch (op) {
          case '[]':
            for (ConstantMapEntry entry in receiver.entries) {
              if (entry.key == other) {
                return entry.value;
              }
            }
            return new NullConstant();
        }
      }
    } else if (enableConstFunctions) {
      // Evaluate type arguments of the method invoked.
      List<DartType>? typeArguments = _evaluateTypeArguments(node, arguments);
      if (typeArguments == null) {
        AbortConstant error = _gotError!;
        _gotError = null;
        return error;
      }
      assert(_gotError == null);
      // ignore: unnecessary_null_comparison
      assert(typeArguments != null);

      // Evaluate named arguments of the method invoked.
      final Map<String, Constant>? namedArguments =
          _evaluateNamedArguments(arguments);
      if (namedArguments == null) {
        AbortConstant error = _gotError!;
        _gotError = null;
        return error;
      }
      assert(_gotError == null);
      // ignore: unnecessary_null_comparison
      assert(namedArguments != null);

      if (receiver is FunctionValue && name == Name.callName) {
        return _handleFunctionInvocation(receiver.function, typeArguments,
            positionalArguments, namedArguments,
            functionEnvironment: receiver.environment);
      } else if (receiver is InstanceConstant) {
        final Class instanceClass = receiver.classNode;
        assert(typeEnvironment.hierarchy is ClassHierarchy);
        final Member member = (typeEnvironment.hierarchy as ClassHierarchy)
            .getDispatchTarget(instanceClass, name)!;
        final FunctionNode? function = member.function;

        // TODO(kallentu): Implement [Object] class methods which have backend
        // specific functions that cannot be run by the constant evaluator.
        final bool isObjectMember = member.enclosingClass != null &&
            member.enclosingClass!.name == "Object";
        if (function != null && !isObjectMember) {
          // TODO(johnniwinther): Make [typeArguments] and [namedArguments]
          // required and non-nullable.
          return withNewInstanceBuilder(instanceClass, typeArguments, () {
            final EvaluationEnvironment newEnv = new EvaluationEnvironment();
            for (int i = 0; i < instanceClass.typeParameters.length; i++) {
              newEnv.addTypeParameterValue(
                  instanceClass.typeParameters[i], receiver.typeArguments[i]);
            }

            // Ensure that fields are visible for instance access.
            receiver.fieldValues.forEach((Reference fieldRef, Constant value) =>
                instanceBuilder!.setFieldValue(fieldRef.asField, value));
            return _handleFunctionInvocation(function, receiver.typeArguments,
                positionalArguments, namedArguments,
                functionEnvironment: newEnv);
          });
        }

        switch (op) {
          case 'toString':
            // Default value for toString() of instances.
            return new StringConstant(
                "Instance of '${receiver.classReference.toStringInternal()}'");
        }
      }
    }

    return createErrorConstant(
        node,
        templateConstEvalInvalidMethodInvocation.withArguments(
            op, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitMethodInvocation(MethodInvocation node) {
    // We have no support for generic method invocation at the moment.
    if (node.arguments.types.isNotEmpty && !enableConstFunctions) {
      return createInvalidExpressionConstant(node, "generic method invocation");
    }

    // We have no support for method invocation with named arguments at the
    // moment.
    if (node.arguments.named.isNotEmpty && !enableConstFunctions) {
      return createInvalidExpressionConstant(
          node, "method invocation with named arguments");
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;

    final List<Constant>? positionalArguments =
        _evaluatePositionalArguments(node.arguments);

    if (positionalArguments == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(positionalArguments != null);

    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new MethodInvocation(
              extract(receiver),
              node.name,
              unevaluatedArguments(
                  positionalArguments, {}, node.arguments.types),
              node.interfaceTarget)
            ..fileOffset = node.fileOffset
            ..flags = node.flags);
    }

    return _handleInvocation(node, node.name, receiver, positionalArguments,
        arguments: node.arguments);
  }

  @override
  Constant visitLogicalExpression(LogicalExpression node) {
    final Constant left = _evaluateSubexpression(node.left);
    if (left is AbortConstant) return left;
    if (shouldBeUnevaluated) {
      enterLazy();
      Constant right = _evaluateSubexpression(node.right);
      if (right is AbortConstant) return right;
      leaveLazy();
      return unevaluated(
          node,
          new LogicalExpression(
              extract(left), node.operatorEnum, extract(right)));
    }
    switch (node.operatorEnum) {
      case LogicalExpressionOperator.OR:
        if (left is BoolConstant) {
          if (left.value) return trueConstant;

          final Constant right = _evaluateSubexpression(node.right);
          if (right is AbortConstant) return right;
          if (right is BoolConstant || right is UnevaluatedConstant) {
            return right;
          }

          return createErrorConstant(
              node,
              templateConstEvalInvalidBinaryOperandType.withArguments(
                  logicalExpressionOperatorToString(node.operatorEnum),
                  left,
                  typeEnvironment.coreTypes.boolLegacyRawType,
                  right.getType(_staticTypeContext!),
                  isNonNullableByDefault));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidMethodInvocation.withArguments(
                logicalExpressionOperatorToString(node.operatorEnum),
                left,
                isNonNullableByDefault));
      case LogicalExpressionOperator.AND:
        if (left is BoolConstant) {
          if (!left.value) return falseConstant;

          final Constant right = _evaluateSubexpression(node.right);
          if (right is AbortConstant) return right;
          if (right is BoolConstant || right is UnevaluatedConstant) {
            return right;
          }

          return createErrorConstant(
              node,
              templateConstEvalInvalidBinaryOperandType.withArguments(
                  logicalExpressionOperatorToString(node.operatorEnum),
                  left,
                  typeEnvironment.coreTypes.boolLegacyRawType,
                  right.getType(_staticTypeContext!),
                  isNonNullableByDefault));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidMethodInvocation.withArguments(
                logicalExpressionOperatorToString(node.operatorEnum),
                left,
                isNonNullableByDefault));
      default:
        // Probably unreachable.
        return createErrorConstant(
            node,
            templateConstEvalInvalidMethodInvocation.withArguments(
                logicalExpressionOperatorToString(node.operatorEnum),
                left,
                isNonNullableByDefault));
    }
  }

  @override
  Constant visitConditionalExpression(ConditionalExpression node) {
    final Constant condition = _evaluateSubexpression(node.condition);
    if (condition is AbortConstant) return condition;
    if (condition == trueConstant) {
      return _evaluateSubexpression(node.then);
    } else if (condition == falseConstant) {
      return _evaluateSubexpression(node.otherwise);
    } else if (shouldBeUnevaluated) {
      enterLazy();
      Constant then = _evaluateSubexpression(node.then);
      if (then is AbortConstant) return then;
      Constant otherwise = _evaluateSubexpression(node.otherwise);
      if (otherwise is AbortConstant) return otherwise;
      leaveLazy();
      return unevaluated(
          node,
          new ConditionalExpression(extract(condition), extract(then),
              extract(otherwise), node.staticType));
    } else {
      return createErrorConstant(
          node.condition,
          templateConstEvalInvalidType.withArguments(
              condition,
              typeEnvironment.coreTypes.boolLegacyRawType,
              condition.getType(_staticTypeContext!),
              isNonNullableByDefault));
    }
  }

  @override
  Constant visitInstanceGet(InstanceGet node) {
    if (node.receiver is ThisExpression) {
      // Probably unreachable unless trying to evaluate non-const stuff as
      // const.
      // Access "this" during instance creation.
      if (instanceBuilder == null) {
        return createErrorConstant(node, messageNotAConstantExpression);
      }

      for (final MapEntry<Field, Constant> entry
          in instanceBuilder!.fields.entries) {
        final Field field = entry.key;
        if (field.name == node.name) {
          return entry.value;
        }
      }

      // Meant as a "stable backstop for situations where Fasta fails to
      // rewrite various erroneous constructs into invalid expressions".
      // Probably unreachable.
      return createInvalidExpressionConstant(node,
          'Could not evaluate field get ${node.name} on incomplete instance');
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    if (receiver is StringConstant && node.name.text == 'length') {
      return canonicalize(intFolder.makeIntConstant(receiver.value.length));
    } else if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new InstanceGet(node.kind, extract(receiver), node.name,
              resultType: node.resultType,
              interfaceTarget: node.interfaceTarget));
    } else if (receiver is NullConstant) {
      return createErrorConstant(node, messageConstEvalNullValue);
    } else if (receiver is ListConstant && enableConstFunctions) {
      switch (node.name.text) {
        case 'first':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          }
          return receiver.entries.first;
        case 'isEmpty':
          return new BoolConstant(receiver.entries.isEmpty);
        case 'isNotEmpty':
          return new BoolConstant(receiver.entries.isNotEmpty);
        // TODO(kallentu): case 'iterator'
        case 'last':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          }
          return receiver.entries.last;
        case 'length':
          return new IntConstant(receiver.entries.length);
        // TODO(kallentu): case 'reversed'
        case 'single':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          } else if (receiver.entries.length > 1) {
            return new _AbortDueToThrowConstant(
                node, new StateError('Too many elements'));
          }
          return receiver.entries.single;
      }
    } else if (receiver is InstanceConstant && enableConstFunctions) {
      for (final MapEntry<Reference, Constant> entry
          in receiver.fieldValues.entries) {
        final Field field = entry.key.asField;
        if (field.name == node.name) {
          return entry.value;
        }
      }
    }
    return createErrorConstant(
        node,
        templateConstEvalInvalidPropertyGet.withArguments(
            node.name.text, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitDynamicGet(DynamicGet node) {
    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    if (receiver is StringConstant && node.name.text == 'length') {
      return canonicalize(intFolder.makeIntConstant(receiver.value.length));
    } else if (shouldBeUnevaluated) {
      return unevaluated(
          node, new DynamicGet(node.kind, extract(receiver), node.name));
    } else if (receiver is NullConstant) {
      return createErrorConstant(node, messageConstEvalNullValue);
    }
    return createErrorConstant(
        node,
        templateConstEvalInvalidPropertyGet.withArguments(
            node.name.text, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitInstanceTearOff(InstanceTearOff node) {
    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    return createErrorConstant(
        node,
        templateConstEvalInvalidPropertyGet.withArguments(
            node.name.text, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitFunctionTearOff(FunctionTearOff node) {
    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    return createErrorConstant(
        node,
        templateConstEvalInvalidPropertyGet.withArguments(
            Name.callName.text, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitPropertyGet(PropertyGet node) {
    if (node.receiver is ThisExpression) {
      // Probably unreachable unless trying to evaluate non-const stuff as
      // const.
      // Access "this" during instance creation.
      if (instanceBuilder == null) {
        return createErrorConstant(node, messageNotAConstantExpression);
      }

      for (final MapEntry<Field, Constant> entry
          in instanceBuilder!.fields.entries) {
        final Field field = entry.key;
        if (field.name == node.name) {
          return entry.value;
        }
      }

      // Meant as a "stable backstop for situations where Fasta fails to
      // rewrite various erroneous constructs into invalid expressions".
      // Probably unreachable.
      return createInvalidExpressionConstant(node,
          'Could not evaluate field get ${node.name} on incomplete instance');
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is AbortConstant) return receiver;
    if (receiver is StringConstant && node.name.text == 'length') {
      return canonicalize(intFolder.makeIntConstant(receiver.value.length));
    } else if (shouldBeUnevaluated) {
      return unevaluated(node,
          new PropertyGet(extract(receiver), node.name, node.interfaceTarget));
    } else if (receiver is NullConstant) {
      return createErrorConstant(node, messageConstEvalNullValue);
    } else if (receiver is ListConstant && enableConstFunctions) {
      switch (node.name.text) {
        case 'first':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          }
          return receiver.entries.first;
        case 'isEmpty':
          return new BoolConstant(receiver.entries.isEmpty);
        case 'isNotEmpty':
          return new BoolConstant(receiver.entries.isNotEmpty);
        // TODO(kallentu): case 'iterator'
        case 'last':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          }
          return receiver.entries.last;
        case 'length':
          return new IntConstant(receiver.entries.length);
        // TODO(kallentu): case 'reversed'
        case 'single':
          if (receiver.entries.isEmpty) {
            return new _AbortDueToThrowConstant(
                node, new StateError('No element'));
          } else if (receiver.entries.length > 1) {
            return new _AbortDueToThrowConstant(
                node, new StateError('Too many elements'));
          }
          return receiver.entries.single;
      }
    } else if (receiver is InstanceConstant && enableConstFunctions) {
      for (final MapEntry<Reference, Constant> entry
          in receiver.fieldValues.entries) {
        final Field field = entry.key.asField;
        if (field.name == node.name) {
          return entry.value;
        }
      }
    }
    return createErrorConstant(
        node,
        templateConstEvalInvalidPropertyGet.withArguments(
            node.name.text, receiver, isNonNullableByDefault));
  }

  @override
  Constant visitLet(Let node) {
    Constant value = _evaluateSubexpression(node.variable.initializer!);
    if (value is AbortConstant) return value;
    env.addVariableValue(node.variable, value);
    return _evaluateSubexpression(node.body);
  }

  @override
  Constant visitVariableGet(VariableGet node) {
    // Not every variable which a [VariableGet] refers to must be marked as
    // constant.  For example function parameters as well as constructs
    // desugared to [Let] expressions are ok.
    //
    // TODO(kustermann): The heuristic of allowing all [VariableGet]s on [Let]
    // variables might allow more than it should.
    final VariableDeclaration variable = node.variable;
    if (enableConstFunctions) {
      return env.lookupVariable(variable) ??
          createErrorConstant(
              node,
              templateConstEvalGetterNotFound
                  .withArguments(variable.name ?? ''));
    } else {
      if (variable.parent is Let || _isFormalParameter(variable)) {
        return env.lookupVariable(node.variable) ??
            createErrorConstant(
                node,
                templateConstEvalNonConstantVariableGet
                    .withArguments(variable.name ?? ''));
      }
      if (variable.isConst) {
        return _evaluateSubexpression(variable.initializer!);
      }
    }
    return createInvalidExpressionConstant(
        node, 'Variable get of a non-const variable.');
  }

  @override
  Constant visitVariableSet(VariableSet node) {
    if (enableConstFunctions) {
      final VariableDeclaration variable = node.variable;
      Constant value = _evaluateSubexpression(node.value);
      if (value is AbortConstant) return value;
      return env.updateVariableValue(variable, value) ??
          createInvalidExpressionConstant(
              node, 'Variable set of an unknown value.');
    }
    return defaultExpression(node);
  }

  /// Computes the constant for [expression] defined in the context of [member].
  ///
  /// This compute the constant as seen in the current evaluation mode even when
  /// the constant is defined in a library compiled with the agnostic evaluation
  /// mode.
  Constant _evaluateExpressionInContext(Member member, Expression expression) {
    StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
    _staticTypeContext = new StaticTypeContext(member, typeEnvironment);
    Constant constant = _evaluateSubexpression(expression);
    if (constant is! AbortConstant) {
      if (_staticTypeContext!.nonNullableByDefaultCompiledMode ==
              NonNullableByDefaultCompiledMode.Agnostic &&
          evaluationMode == EvaluationMode.weak) {
        constant = _weakener.visitConstant(constant) ?? constant;
      }
    }
    _staticTypeContext = oldStaticTypeContext;
    return constant;
  }

  @override
  Constant visitStaticGet(StaticGet node) {
    return withNewEnvironment(() {
      final Member target = node.target;
      if (target is Field) {
        if (target.isConst) {
          return _evaluateExpressionInContext(target, target.initializer!);
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidStaticInvocation
                .withArguments(target.name.text));
      } else if (target is Procedure) {
        if (target.kind == ProcedureKind.Method) {
          return canonicalize(new TearOffConstant(target));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidStaticInvocation
                .withArguments(target.name.text));
      } else {
        return createInvalidExpressionConstant(
            node, 'No support for ${target.runtimeType} in a static-get.');
      }
    });
  }

  @override
  Constant visitStaticTearOff(StaticTearOff node) {
    return withNewEnvironment(() {
      final Member target = node.target;
      if (target is Procedure) {
        if (target.kind == ProcedureKind.Method) {
          return canonicalize(new TearOffConstant(target));
        }
        return createErrorConstant(
            node,
            templateConstEvalInvalidStaticInvocation
                .withArguments(target.name.text));
      } else {
        return createInvalidExpressionConstant(
            node, 'No support for ${target.runtimeType} in a static tear-off.');
      }
    });
  }

  @override
  Constant visitStringConcatenation(StringConcatenation node) {
    final List<Object> concatenated = <Object>[new StringBuffer()];
    for (int i = 0; i < node.expressions.length; i++) {
      Constant constant = _evaluateSubexpression(node.expressions[i]);
      if (constant is AbortConstant) return constant;
      if (constant is PrimitiveConstant<Object>) {
        String value;
        if (constant is DoubleConstant && intFolder.isInt(constant)) {
          value = new BigInt.from(constant.value).toString();
        } else {
          value = constant.value.toString();
        }
        Object last = concatenated.last;
        if (last is StringBuffer) {
          last.write(value);
        } else {
          concatenated.add(new StringBuffer(value));
        }
      } else if (shouldBeUnevaluated) {
        // The constant is either unevaluated or a non-primitive in an
        // unevaluated context. In both cases we defer the evaluation and/or
        // error reporting till later.
        concatenated.add(constant);
      } else {
        return createErrorConstant(
            node,
            templateConstEvalInvalidStringInterpolationOperand.withArguments(
                constant, isNonNullableByDefault));
      }
    }
    if (concatenated.length > 1) {
      final List<Expression> expressions =
          new List<Expression>.generate(concatenated.length, (int i) {
        Object value = concatenated[i];
        if (value is StringBuffer) {
          return new ConstantExpression(
              canonicalize(new StringConstant(value.toString())));
        } else {
          // The value is either unevaluated constant or a non-primitive
          // constant in an unevaluated expression.
          return extract(value as Constant);
        }
      }, growable: false);
      return unevaluated(node, new StringConcatenation(expressions));
    }
    return canonicalize(new StringConstant(concatenated.single.toString()));
  }

  Constant _getFromEnvironmentDefaultValue(Procedure target) {
    VariableDeclaration variable = target.function.namedParameters
        .singleWhere((v) => v.name == 'defaultValue');
    return variable.initializer != null
        ? _evaluateExpressionInContext(target, variable.initializer!)
        :
        // Not reachable unless a defaultValue in fromEnvironment in dart:core
        // becomes null.
        nullConstant;
  }

  Constant _handleFromEnvironment(
      Procedure target, StringConstant name, Map<String, Constant> named) {
    String? value = environmentDefines![name.value];
    Constant? defaultValue = named["defaultValue"];
    if (target.enclosingClass == coreTypes.boolClass) {
      Constant boolConstant;
      if (value == "true") {
        boolConstant = trueConstant;
      } else if (value == "false") {
        boolConstant = falseConstant;
      } else if (defaultValue != null) {
        if (defaultValue is BoolConstant) {
          boolConstant = makeBoolConstant(defaultValue.value);
        } else if (defaultValue is NullConstant) {
          boolConstant = nullConstant;
        } else {
          // Probably unreachable.
          boolConstant = falseConstant;
        }
      } else {
        boolConstant = _getFromEnvironmentDefaultValue(target);
      }
      return boolConstant;
    } else if (target.enclosingClass == coreTypes.intClass) {
      int? intValue = value != null ? int.tryParse(value) : null;
      Constant intConstant;
      if (intValue != null) {
        bool negated = value!.startsWith('-');
        intConstant = intFolder.makeIntConstant(intValue, unsigned: !negated);
      } else if (defaultValue != null) {
        if (intFolder.isInt(defaultValue)) {
          intConstant = defaultValue;
        } else {
          intConstant = nullConstant;
        }
      } else {
        intConstant = _getFromEnvironmentDefaultValue(target);
      }
      return canonicalize(intConstant);
    } else if (target.enclosingClass == coreTypes.stringClass) {
      Constant stringConstant;
      if (value != null) {
        stringConstant = canonicalize(new StringConstant(value));
      } else if (defaultValue != null) {
        if (defaultValue is StringConstant) {
          stringConstant = defaultValue;
        } else {
          stringConstant = nullConstant;
        }
      } else {
        stringConstant = _getFromEnvironmentDefaultValue(target);
      }
      return stringConstant;
    }
    // Unreachable until fromEnvironment is added to other classes in dart:core
    // than bool, int and String.
    throw new UnsupportedError(
        'Unexpected fromEnvironment constructor: $target');
  }

  Constant _handleHasEnvironment(StringConstant name) {
    return environmentDefines!.containsKey(name.value)
        ? trueConstant
        : falseConstant;
  }

  @override
  Constant visitStaticInvocation(StaticInvocation node) {
    final Procedure target = node.target;
    final Arguments arguments = node.arguments;
    List<DartType>? types = _evaluateTypeArguments(node, arguments);
    if (types == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(types != null);

    final List<DartType> typeArguments = convertTypes(types);

    final List<Constant>? positionals = _evaluatePositionalArguments(arguments);
    if (positionals == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(positionals != null);

    final Map<String, Constant>? named = _evaluateNamedArguments(arguments);
    if (named == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(named != null);

    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new StaticInvocation(
              target, unevaluatedArguments(positionals, named, arguments.types),
              isConst: true));
    }
    if (target.kind == ProcedureKind.Factory) {
      if (target.isConst &&
          target.enclosingLibrary == coreTypes.coreLibrary &&
          positionals.length == 1 &&
          (target.name.text == "fromEnvironment" ||
              target.name.text == "hasEnvironment")) {
        if (environmentDefines != null) {
          // Evaluate environment constant.
          Constant name = positionals.single;
          if (name is StringConstant) {
            if (target.name.text == "fromEnvironment") {
              return _handleFromEnvironment(target, name, named);
            } else {
              return _handleHasEnvironment(name);
            }
          } else if (name is NullConstant) {
            return createErrorConstant(node, messageConstEvalNullValue);
          }
        } else {
          // Leave environment constant unevaluated.
          return unevaluated(
              node,
              new StaticInvocation(target,
                  unevaluatedArguments(positionals, named, arguments.types),
                  isConst: true));
        }
      }
    } else if (target.name.text == 'identical') {
      // Ensure the "identical()" function comes from dart:core.
      final TreeNode? parent = target.parent;
      if (parent is Library && parent == coreTypes.coreLibrary) {
        final Constant left = positionals[0];
        final Constant right = positionals[1];

        Constant evaluateIdentical() {
          // Since we canonicalize constants during the evaluation, we can use
          // identical here.
          Constant result = makeBoolConstant(identical(left, right));
          if (evaluationMode == EvaluationMode.agnostic) {
            Constant? weakLeft = _weakener.visitConstant(left);
            Constant? weakRight = _weakener.visitConstant(right);
            if (weakLeft != null || weakRight != null) {
              Constant weakResult = makeBoolConstant(
                  identical(weakLeft ?? left, weakRight ?? right));
              if (!identical(result, weakResult)) {
                return createErrorConstant(node, messageNonAgnosticConstant);
              }
            }
          }
          return result;
        }

        if (targetingJavaScript) {
          // In JavaScript, we lower [identical] to `===`, so we need to take
          // the double special cases into account.
          return doubleSpecialCases(left, right) ?? evaluateIdentical();
        }
        return evaluateIdentical();
      }
    } else if (target.isExtensionMember) {
      return createErrorConstant(node, messageConstEvalExtension);
    } else if (enableConstFunctions && target.kind == ProcedureKind.Method) {
      return _handleFunctionInvocation(
          node.target.function, typeArguments, positionals, named);
    }

    String name = target.name.text;
    if (target is Procedure && target.isFactory) {
      if (name.isEmpty) {
        name = target.enclosingClass!.name;
      } else {
        name = '${target.enclosingClass!.name}.${name}';
      }

      if (enableConstFunctions) {
        return _handleFunctionInvocation(
            node.target.function, typeArguments, positionals, named);
      }
    }
    return createInvalidExpressionConstant(node, "Invocation of $name");
  }

  Constant _handleFunctionInvocation(
      FunctionNode function,
      List<DartType> typeArguments,
      List<Constant> positionalArguments,
      Map<String, Constant> namedArguments,
      {EvaluationEnvironment? functionEnvironment}) {
    Constant executeFunction() {
      // Map arguments from caller to callee.
      for (int i = 0; i < function.typeParameters.length; i++) {
        env.addTypeParameterValue(function.typeParameters[i], typeArguments[i]);
      }
      for (int i = 0; i < function.positionalParameters.length; i++) {
        final VariableDeclaration parameter = function.positionalParameters[i];
        final Constant value = (i < positionalArguments.length)
            ? positionalArguments[i]
            // TODO(johnniwinther): This should call [_evaluateSubexpression].
            : _evaluateNullableSubexpression(parameter.initializer);
        if (value is AbortConstant) return value;
        env.addVariableValue(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);
      }

      final Constant result = executeBody(function.body!);
      if (result is NullConstant &&
          function.returnType.nullability == Nullability.nonNullable) {
        // Ensure that the evaluated constant returned is not null if the
        // function has a non-nullable return type.
        return createErrorConstant(
            function,
            templateConstEvalInvalidType.withArguments(
                result,
                function.returnType,
                result.getType(_staticTypeContext!),
                isNonNullableByDefault));
      }
      return result;
    }

    if (functionEnvironment != null) {
      return withEnvironment(functionEnvironment, executeFunction);
    }
    return withNewEnvironment(executeFunction);
  }

  @override
  Constant visitAsExpression(AsExpression node) {
    final Constant constant = _evaluateSubexpression(node.operand);
    if (constant is AbortConstant) return constant;
    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new AsExpression(extract(constant), env.substituteType(node.type))
            ..isForNonNullableByDefault =
                _staticTypeContext!.isNonNullableByDefault);
    }
    DartType? type = _evaluateDartType(node, node.type);
    if (type == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(type != null);
    return ensureIsSubtype(constant, type, node);
  }

  @override
  Constant visitIsExpression(IsExpression node) {
    final Constant constant = _evaluateSubexpression(node.operand);
    if (constant is AbortConstant) return constant;
    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new IsExpression(extract(constant), node.type)
            ..fileOffset = node.fileOffset
            ..flags = node.flags);
    }

    DartType? type = _evaluateDartType(node, node.type);
    if (type == null) {
      AbortConstant error = _gotError!;
      _gotError = null;
      return error;
    }
    assert(_gotError == null);
    // ignore: unnecessary_null_comparison
    assert(type != null);

    bool performIs(Constant constant, {required bool strongMode}) {
      // ignore: unnecessary_null_comparison
      assert(strongMode != null);
      if (strongMode) {
        return isSubtype(constant, type, SubtypeCheckMode.withNullabilities);
      } else {
        // In weak checking mode: if e evaluates to a value v and v has runtime
        // type S, an instance check e is T occurring in a legacy library or an
        // opted-in library is evaluated as follows:
        //
        //    If v is null and T is a legacy type,
        //       return LEGACY_SUBTYPE(T, NULL) || LEGACY_SUBTYPE(Object, T)
        //    If v is null and T is not a legacy type,
        //       return NNBD_SUBTYPE(NULL, T)
        //    Otherwise return LEGACY_SUBTYPE(S, T)
        if (constant is NullConstant) {
          if (type.nullability == Nullability.legacy) {
            // `null is Null` is handled below.
            return typeEnvironment.isSubtypeOf(type, const NullType(),
                    SubtypeCheckMode.ignoringNullabilities) ||
                typeEnvironment.isSubtypeOf(typeEnvironment.objectLegacyRawType,
                    type, SubtypeCheckMode.ignoringNullabilities);
          } else {
            return typeEnvironment.isSubtypeOf(
                const NullType(), type, SubtypeCheckMode.withNullabilities);
          }
        }
        return isSubtype(
            constant, type, SubtypeCheckMode.ignoringNullabilities);
      }
    }

    switch (evaluationMode) {
      case EvaluationMode.strong:
        return makeBoolConstant(performIs(constant, strongMode: true));
      case EvaluationMode.agnostic:
        bool strongResult = performIs(constant, strongMode: true);
        Constant weakConstant = _weakener.visitConstant(constant) ?? constant;
        bool weakResult = performIs(weakConstant, strongMode: false);
        if (strongResult != weakResult) {
          return createErrorConstant(node, messageNonAgnosticConstant);
        }
        return makeBoolConstant(strongResult);
      case EvaluationMode.weak:
        return makeBoolConstant(performIs(constant, strongMode: false));
    }
  }

  @override
  Constant visitNot(Not node) {
    final Constant constant = _evaluateSubexpression(node.operand);
    if (constant is AbortConstant) return constant;
    if (constant is BoolConstant) {
      return makeBoolConstant(constant != trueConstant);
    }
    if (shouldBeUnevaluated) {
      return unevaluated(node, new Not(extract(constant)));
    }
    return createErrorConstant(
        node,
        templateConstEvalInvalidType.withArguments(
            constant,
            typeEnvironment.coreTypes.boolLegacyRawType,
            constant.getType(_staticTypeContext!),
            isNonNullableByDefault));
  }

  @override
  Constant visitNullCheck(NullCheck node) {
    final Constant constant = _evaluateSubexpression(node.operand);
    if (constant is AbortConstant) return constant;
    if (constant is NullConstant) {
      return createErrorConstant(node, messageConstEvalNonNull);
    }
    if (shouldBeUnevaluated) {
      return unevaluated(node, new NullCheck(extract(constant)));
    }
    return constant;
  }

  @override
  Constant visitSymbolLiteral(SymbolLiteral node) {
    final Reference? libraryReference =
        node.value.startsWith('_') ? libraryOf(node).reference : null;
    return canonicalize(new SymbolConstant(node.value, libraryReference));
  }

  @override
  Constant visitThrow(Throw node) {
    if (enableConstFunctions) {
      final Constant value = _evaluateSubexpression(node.expression);
      if (value is AbortConstant) return value;
      return new _AbortDueToThrowConstant(node, value);
    }
    return defaultExpression(node);
  }

  @override
  Constant visitInstantiation(Instantiation node) {
    final Constant constant = _evaluateSubexpression(node.expression);
    if (constant is AbortConstant) return constant;
    if (shouldBeUnevaluated) {
      return unevaluated(
          node,
          new Instantiation(extract(constant),
              node.typeArguments.map((t) => env.substituteType(t)).toList()));
    }
    if (constant is TearOffConstant) {
      if (node.typeArguments.length ==
          constant.procedure.function.typeParameters.length) {
        List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
        if (types == null) {
          AbortConstant error = _gotError!;
          _gotError = null;
          return error;
        }
        assert(_gotError == null);
        // ignore: unnecessary_null_comparison
        assert(types != null);

        final List<DartType> typeArguments = convertTypes(types);
        return canonicalize(
            new PartialInstantiationConstant(constant, typeArguments));
      }
      // Probably unreachable.
      return createInvalidExpressionConstant(
          node,
          'The number of type arguments supplied in the partial instantiation '
          'does not match the number of type arguments of the $constant.');
    }
    // The inner expression in an instantiation can never be null, since
    // instantiations are only inferred on direct references to declarations.
    // Probably unreachable.
    return createInvalidExpressionConstant(
        node, 'Only tear-off constants can be partially instantiated.');
  }

  @override
  Constant visitConstructorTearOff(ConstructorTearOff node) {
    return defaultExpression(node);
  }

  @override
  Constant visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
    return createErrorConstant(node,
        templateConstEvalDeferredLibrary.withArguments(node.import.name!));
  }

  // Helper methods:

  /// If both constants are DoubleConstant whose values would give different
  /// results from == and [identical], return the result of ==. Otherwise
  /// return null.
  Constant? doubleSpecialCases(Constant a, Constant b) {
    if (a is DoubleConstant && b is DoubleConstant) {
      if (a.value.isNaN && b.value.isNaN) return falseConstant;
      if (a.value == 0.0 && b.value == 0.0) return trueConstant;
    }

    if (a is DoubleConstant && b is IntConstant) {
      return makeBoolConstant(a.value == b.value);
    }

    if (a is IntConstant && b is DoubleConstant) {
      return makeBoolConstant(a.value == b.value);
    }
    return null;
  }

  bool hasPrimitiveEqual(Constant constant) {
    if (intFolder.isInt(constant)) return true;
    DartType type = constant.getType(_staticTypeContext!);
    return !(type is InterfaceType && !classHasPrimitiveEqual(type.classNode));
  }

  bool classHasPrimitiveEqual(Class klass) {
    bool? cached = primitiveEqualCache[klass];
    if (cached != null) return cached;
    for (Procedure procedure in klass.procedures) {
      if (procedure.kind == ProcedureKind.Operator &&
          procedure.name.text == '==' &&
          !procedure.isAbstract &&
          !procedure.isForwardingStub) {
        return primitiveEqualCache[klass] = false;
      }
    }
    if (klass.supertype == null) return true; // To be on the safe side
    return primitiveEqualCache[klass] =
        classHasPrimitiveEqual(klass.supertype!.classNode);
  }

  BoolConstant makeBoolConstant(bool value) =>
      value ? trueConstant : falseConstant;

  bool isSubtype(Constant constant, DartType type, SubtypeCheckMode mode) {
    DartType constantType = constant.getType(_staticTypeContext!);
    if (mode == SubtypeCheckMode.ignoringNullabilities) {
      constantType = rawLegacyErasure(constantType) ?? constantType;
    }
    bool result = typeEnvironment.isSubtypeOf(constantType, type, mode);
    if (targetingJavaScript && !result) {
      if (constantType is InterfaceType &&
          constantType.classNode == typeEnvironment.coreTypes.intClass) {
        // Probably unreachable.
        // With JS semantics, an integer is also a double.
        result = typeEnvironment.isSubtypeOf(
            new InterfaceType(typeEnvironment.coreTypes.doubleClass,
                constantType.nullability, const <DartType>[]),
            type,
            mode);
      } else if (intFolder.isInt(constant)) {
        // With JS semantics, an integer valued double is also an int.
        result = typeEnvironment.isSubtypeOf(
            new InterfaceType(typeEnvironment.coreTypes.intClass,
                constantType.nullability, const <DartType>[]),
            type,
            mode);
      }
    }
    return result;
  }

  /// Note that this returns an error-constant on error and as such the
  /// return value should be checked.
  Constant ensureIsSubtype(Constant constant, DartType type, TreeNode node) {
    bool result;
    switch (evaluationMode) {
      case EvaluationMode.strong:
        result = isSubtype(constant, type, SubtypeCheckMode.withNullabilities);
        break;
      case EvaluationMode.agnostic:
        bool strongResult =
            isSubtype(constant, type, SubtypeCheckMode.withNullabilities);
        Constant weakConstant = _weakener.visitConstant(constant) ?? constant;
        bool weakResult = isSubtype(
            weakConstant, type, SubtypeCheckMode.ignoringNullabilities);
        if (strongResult != weakResult) {
          return createErrorConstant(node, messageNonAgnosticConstant);
        }
        result = strongResult;
        break;
      case EvaluationMode.weak:
        result =
            isSubtype(constant, type, SubtypeCheckMode.ignoringNullabilities);
        break;
    }
    if (!result) {
      return createErrorConstant(
          node,
          templateConstEvalInvalidType.withArguments(constant, type,
              constant.getType(_staticTypeContext!), isNonNullableByDefault));
    }
    return constant;
  }

  /// Returns the types on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  List<DartType>? _evaluateTypeArguments(TreeNode node, Arguments arguments) {
    return _evaluateDartTypes(node, arguments.types);
  }

  /// Returns the types on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  List<DartType>? _evaluateSuperTypeArguments(TreeNode node, Supertype type) {
    return _evaluateDartTypes(node, type.typeArguments);
  }

  /// Upon failure in certain procedure calls (e.g. [_evaluateDartTypes]) the
  /// "error"-constant is saved here. Normally this should be null.
  /// Once a caller calls such a procedure and it gives an error here,
  /// the caller should fetch it an null-out this variable.
  AbortConstant? _gotError;

  /// Returns the types on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  List<DartType>? _evaluateDartTypes(TreeNode node, List<DartType> types) {
    // TODO: Once the frontend guarantees that there are no free type variables
    // left over after substitution, we can enable this shortcut again:
    // if (env.isEmpty) return types;
    List<DartType> result =
        new List<DartType>.filled(types.length, dummyDartType, growable: true);
    for (int i = 0; i < types.length; i++) {
      DartType? type = _evaluateDartType(node, types[i]);
      if (type == null) {
        return null;
      }
      assert(_gotError == null);
      // ignore: unnecessary_null_comparison
      assert(type != null);
      result[i] = type;
    }
    return result;
  }

  /// Returns the type on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  DartType? _evaluateDartType(TreeNode node, DartType type) {
    final DartType result = env.substituteType(type);

    if (!isInstantiated(result)) {
      _gotError = createErrorConstant(
          node,
          templateConstEvalFreeTypeParameter.withArguments(
              type, isNonNullableByDefault));
      return null;
    }

    return result;
  }

  /// Returns the types on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  List<Constant>? _evaluatePositionalArguments(Arguments arguments) {
    List<Constant> result = new List<Constant>.filled(
        arguments.positional.length, dummyConstant,
        growable: true);
    for (int i = 0; i < arguments.positional.length; i++) {
      Constant constant = _evaluateSubexpression(arguments.positional[i]);
      if (constant is AbortConstant) {
        _gotError = constant;
        return null;
      }
      result[i] = constant;
    }
    return result;
  }

  /// Returns the arguments on success and null on failure.
  /// Note that on failure an errorConstant is saved in [_gotError].
  Map<String, Constant>? _evaluateNamedArguments(Arguments arguments) {
    if (arguments.named.isEmpty) return const <String, Constant>{};

    final Map<String, Constant> named = {};
    for (NamedExpression pair in arguments.named) {
      if (_gotError != null) return null;
      Constant constant = _evaluateSubexpression(pair.value);
      if (constant is AbortConstant) {
        _gotError = constant;
        return null;
      }
      named[pair.name] = constant;
    }
    if (_gotError != null) return null;
    return named;
  }

  Arguments unevaluatedArguments(List<Constant> positionalArgs,
      Map<String, Constant> namedArgs, List<DartType> types) {
    final List<Expression> positional =
        new List<Expression>.filled(positionalArgs.length, dummyExpression);
    final List<NamedExpression> named = new List<NamedExpression>.filled(
        namedArgs.length, dummyNamedExpression);
    for (int i = 0; i < positionalArgs.length; ++i) {
      positional[i] = extract(positionalArgs[i]);
    }
    int i = 0;
    namedArgs.forEach((String name, Constant value) {
      named[i++] = new NamedExpression(name, extract(value));
    });
    return new Arguments(positional, named: named, types: types);
  }

  Constant canonicalize(Constant constant) {
    // Don't use putIfAbsent to avoid the context allocation needed
    // for the closure.
    return canonicalizationCache[constant] ??= constant;
  }

  T withNewInstanceBuilder<T>(
      Class klass, List<DartType> typeArguments, T fn()) {
    InstanceBuilder? old = instanceBuilder;
    instanceBuilder = new InstanceBuilder(this, klass, typeArguments);
    T result = fn();
    instanceBuilder = old;
    return result;
  }

  T withNewEnvironment<T>(T fn()) {
    final EvaluationEnvironment oldEnv = env;
    if (enableConstFunctions) {
      env = new EvaluationEnvironment.withParent(env);
    } else {
      env = new EvaluationEnvironment();
    }
    T result = fn();
    env = oldEnv;
    return result;
  }

  T withEnvironment<T>(EvaluationEnvironment newEnv, T fn()) {
    final EvaluationEnvironment oldEnv = env;
    env = newEnv;
    T result = fn();
    env = oldEnv;
    return result;
  }

  /// Binary operation between two operands, at least one of which is a double.
  Constant evaluateBinaryNumericOperation(
      String op, num a, num b, Expression node) {
    switch (op) {
      case '+':
        return new DoubleConstant((a + b) as double);
      case '-':
        return new DoubleConstant((a - b) as double);
      case '*':
        return new DoubleConstant((a * b) as double);
      case '/':
        return new DoubleConstant(a / b);
      case '~/':
        if (b == 0) {
          return createErrorConstant(
              node, templateConstEvalZeroDivisor.withArguments(op, '$a'));
        }
        return intFolder.truncatingDivide(node, a, b);
      case '%':
        return new DoubleConstant((a % b) as double);
    }

    switch (op) {
      case '<':
        return makeBoolConstant(a < b);
      case '<=':
        return makeBoolConstant(a <= b);
      case '>=':
        return makeBoolConstant(a >= b);
      case '>':
        return makeBoolConstant(a > b);
    }

    // Probably unreachable.
    return createInvalidExpressionConstant(
        node, "Unexpected binary numeric operation '$op'.");
  }

  // TODO(johnniwinther): Remove the need for this by adding a current library
  // field.
  Library libraryOf(TreeNode? node) {
    // The tree structure of the kernel AST ensures we always have an enclosing
    // library.
    while (true) {
      if (node is Library) return node;
      node = node!.parent;
    }
  }

  @override
  Constant defaultBasicLiteral(BasicLiteral node) => defaultExpression(node);

  @override
  Constant visitAwaitExpression(AwaitExpression node) =>
      defaultExpression(node);

  @override
  Constant visitBlockExpression(BlockExpression node) =>
      defaultExpression(node);

  @override
  Constant visitDynamicSet(DynamicSet node) => defaultExpression(node);

  @override
  Constant visitInstanceGetterInvocation(InstanceGetterInvocation node) =>
      defaultExpression(node);

  @override
  Constant visitInstanceSet(InstanceSet node) => defaultExpression(node);

  @override
  Constant visitLoadLibrary(LoadLibrary node) => defaultExpression(node);

  @override
  Constant visitPropertySet(PropertySet node) => defaultExpression(node);

  @override
  Constant visitRethrow(Rethrow node) => defaultExpression(node);

  @override
  Constant visitStaticSet(StaticSet node) => defaultExpression(node);

  @override
  Constant visitSuperMethodInvocation(SuperMethodInvocation node) =>
      defaultExpression(node);

  @override
  Constant visitSuperPropertyGet(SuperPropertyGet node) =>
      defaultExpression(node);

  @override
  Constant visitSuperPropertySet(SuperPropertySet node) =>
      defaultExpression(node);

  @override
  Constant visitThisExpression(ThisExpression node) => defaultExpression(node);
}

class StatementConstantEvaluator extends StatementVisitor<ExecutionStatus> {
  ConstantEvaluator exprEvaluator;

  StatementConstantEvaluator(this.exprEvaluator) {
    if (!exprEvaluator.enableConstFunctions) {
      throw new UnsupportedError("Const functions feature is not enabled.");
    }
  }

  /// Evaluate the expression using the [ConstantEvaluator].
  Constant evaluate(Expression expr) => expr.accept(exprEvaluator);

  @override
  ExecutionStatus defaultStatement(Statement node) {
    throw new UnsupportedError(
        'Statement constant evaluation does not support ${node.runtimeType}.');
  }

  @override
  ExecutionStatus visitAssertBlock(AssertBlock node) => defaultStatement(node);

  @override
  ExecutionStatus visitAssertStatement(AssertStatement node) {
    AbortConstant? error = exprEvaluator.checkAssert(node);
    if (error != null) return new AbortStatus(error);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitBlock(Block node) {
    return exprEvaluator.withNewEnvironment(() {
      for (Statement statement in node.statements) {
        final ExecutionStatus status = statement.accept(this);
        if (status is! ProceedStatus) return status;
      }
      return const ProceedStatus();
    });
  }

  @override
  ExecutionStatus visitBreakStatement(BreakStatement node) =>
      new BreakStatus(node.target);

  @override
  ExecutionStatus visitContinueSwitchStatement(ContinueSwitchStatement node) =>
      node.target.body.accept(this);

  @override
  ExecutionStatus visitDoStatement(DoStatement node) {
    Constant condition;
    do {
      ExecutionStatus status = node.body.accept(this);
      if (status is! ProceedStatus) return status;
      condition = evaluate(node.condition);
    } while (condition is BoolConstant && condition.value);

    if (condition is AbortConstant) {
      return new AbortStatus(condition);
    }
    assert(condition is BoolConstant);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitEmptyStatement(EmptyStatement node) =>
      const ProceedStatus();

  @override
  ExecutionStatus visitFunctionDeclaration(FunctionDeclaration node) {
    final EvaluationEnvironment newEnv =
        new EvaluationEnvironment.withParent(exprEvaluator.env);
    newEnv.addVariableValue(
        node.variable, new FunctionValue(node.function, null));
    final FunctionValue function = new FunctionValue(node.function, newEnv);
    exprEvaluator.env.addVariableValue(node.variable, function);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitIfStatement(IfStatement node) {
    Constant condition = evaluate(node.condition);
    if (condition is AbortConstant) return new AbortStatus(condition);
    assert(condition is BoolConstant);
    if ((condition as BoolConstant).value) {
      return node.then.accept(this);
    } else if (node.otherwise != null) {
      return node.otherwise!.accept(this);
    }
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitForStatement(ForStatement node) {
    for (VariableDeclaration variable in node.variables) {
      final ExecutionStatus status = variable.accept(this);
      if (status is! ProceedStatus) return status;
    }

    Constant? condition =
        node.condition != null ? evaluate(node.condition!) : null;
    while (node.condition == null || condition is BoolConstant) {
      if (condition is BoolConstant && !condition.value) break;

      final ExecutionStatus status = node.body.accept(this);
      if (status is! ProceedStatus) return status;

      for (Expression update in node.updates) {
        Constant updateConstant = evaluate(update);
        if (updateConstant is AbortConstant) {
          return new AbortStatus(updateConstant);
        }
      }

      if (node.condition != null) {
        condition = evaluate(node.condition!);
      }
    }

    if (condition is AbortConstant) return new AbortStatus(condition);
    assert(condition is BoolConstant);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitExpressionStatement(ExpressionStatement node) {
    Constant value = evaluate(node.expression);
    if (value is AbortConstant) return new AbortStatus(value);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitLabeledStatement(LabeledStatement node) {
    final ExecutionStatus status = node.body.accept(this);
    if (status is BreakStatus && status.target == node) {
      return const ProceedStatus();
    }
    return status;
  }

  @override
  ExecutionStatus visitReturnStatement(ReturnStatement node) {
    Constant? result;
    if (node.expression != null) {
      result = evaluate(node.expression!);
      if (result is AbortConstant) return new AbortStatus(result);
    }
    return new ReturnStatus(result);
  }

  @override
  ExecutionStatus visitSwitchStatement(SwitchStatement node) {
    final Constant value = evaluate(node.expression);
    if (value is AbortConstant) return new AbortStatus(value);

    for (SwitchCase switchCase in node.cases) {
      if (switchCase.isDefault) return switchCase.body.accept(this);
      for (Expression expr in switchCase.expressions) {
        final Constant caseValue = evaluate(expr);
        if (value == caseValue) return switchCase.body.accept(this);
      }
    }
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitTryCatch(TryCatch node) {
    final ExecutionStatus tryStatus = node.body.accept(this);
    if (tryStatus is AbortStatus) {
      final Constant error = tryStatus.error;
      if (error is _AbortDueToThrowConstant) {
        final Object throwValue = error.throwValue;
        final DartType defaultType =
            exprEvaluator.typeEnvironment.coreTypes.objectNonNullableRawType;

        DartType? throwType;
        if (throwValue is Constant) {
          throwType = throwValue.getType(exprEvaluator._staticTypeContext!);
        } else if (throwValue is StateError) {
          final Class stateErrorClass = exprEvaluator
              .coreTypes.coreLibrary.classes
              .firstWhere((Class klass) => klass.name == 'StateError');
          throwType =
              new InterfaceType(stateErrorClass, Nullability.nonNullable);
        } else if (throwValue is RangeError) {
          final Class rangeErrorClass = exprEvaluator
              .coreTypes.coreLibrary.classes
              .firstWhere((Class klass) => klass.name == 'RangeError');
          throwType =
              new InterfaceType(rangeErrorClass, Nullability.nonNullable);
        }
        assert(throwType != null);

        for (Catch catchClause in node.catches) {
          if (exprEvaluator.typeEnvironment.isSubtypeOf(throwType!,
                  catchClause.guard, SubtypeCheckMode.withNullabilities) ||
              catchClause.guard == defaultType) {
            return exprEvaluator.withNewEnvironment(() {
              if (catchClause.exception != null) {
                // TODO(kallentu): Store non-constant exceptions.
                if (throwValue is Constant) {
                  exprEvaluator.env
                      .addVariableValue(catchClause.exception!, throwValue);
                }
              }
              // TODO(kallentu): Store appropriate stack trace in environment.
              return catchClause.body.accept(this);
            });
          }
        }
      }
    }
    return tryStatus;
  }

  @override
  ExecutionStatus visitTryFinally(TryFinally node) {
    final ExecutionStatus tryStatus = node.body.accept(this);
    final ExecutionStatus finallyStatus = node.finalizer.accept(this);
    if (finallyStatus is! ProceedStatus) return finallyStatus;
    return tryStatus;
  }

  @override
  ExecutionStatus visitVariableDeclaration(VariableDeclaration node) {
    Constant value;
    if (node.initializer != null) {
      value = evaluate(node.initializer!);
      if (value is AbortConstant) return new AbortStatus(value);
    } else {
      value = new NullConstant();
    }
    exprEvaluator.env.addVariableValue(node, value);
    return const ProceedStatus();
  }

  @override
  ExecutionStatus visitWhileStatement(WhileStatement node) {
    Constant condition = evaluate(node.condition);
    while (condition is BoolConstant && condition.value) {
      final ExecutionStatus status = node.body.accept(this);
      if (status is! ProceedStatus) return status;
      condition = evaluate(node.condition);
    }
    if (condition is AbortConstant) return new AbortStatus(condition);
    assert(condition is BoolConstant);
    return const ProceedStatus();
  }
}

class ConstantCoverage {
  final Map<Uri, Set<Reference>> constructorCoverage;

  ConstantCoverage(this.constructorCoverage);
}

/// Holds the necessary information for a constant object, namely
///   * the [klass] being instantiated
///   * the [typeArguments] used for the instantiation
///   * the [fields] the instance will obtain (all fields from the
///     instantiated [klass] up to the [Object] klass).
class InstanceBuilder {
  ConstantEvaluator evaluator;

  /// The class of the new instance.
  final Class klass;

  /// The values of the type parameters of the new instance.
  final List<DartType> typeArguments;

  /// The field values of the new instance.
  final Map<Field, Constant> fields = <Field, Constant>{};

  final List<AssertStatement> asserts = <AssertStatement>[];

  final List<Expression> unusedArguments = <Expression>[];

  InstanceBuilder(this.evaluator, this.klass, this.typeArguments);

  void setFieldValue(Field field, Constant constant) {
    fields[field] = constant;
  }

  InstanceConstant buildInstance() {
    assert(asserts.isEmpty);
    final Map<Reference, Constant> fieldValues = <Reference, Constant>{};
    fields.forEach((Field field, Constant value) {
      assert(value is! UnevaluatedConstant);
      fieldValues[field.getterReference] = value;
    });
    assert(unusedArguments.isEmpty);
    return new InstanceConstant(klass.reference, typeArguments, fieldValues);
  }

  InstanceCreation buildUnevaluatedInstance() {
    final Map<Reference, Expression> fieldValues = <Reference, Expression>{};
    fields.forEach((Field field, Constant value) {
      fieldValues[field.getterReference] = evaluator.extract(value);
    });
    return new InstanceCreation(
        klass.reference, typeArguments, fieldValues, asserts, unusedArguments);
  }
}

/// Holds an environment of type parameters, parameters and variables.
class EvaluationEnvironment {
  /// The values of the type parameters in scope.
  final Map<TypeParameter, DartType> _typeVariables =
      <TypeParameter, DartType>{};

  /// The references to values of the parameters/variables in scope.
  final Map<VariableDeclaration, EvaluationReference> _variables =
      <VariableDeclaration, EvaluationReference>{};

  /// The variables that hold unevaluated constants.
  ///
  /// Variables are removed from this set when looked up, leaving only the
  /// unread variables at the end.
  final Set<VariableDeclaration> _unreadUnevaluatedVariables =
      new Set<VariableDeclaration>();

  final EvaluationEnvironment? _parent;

  EvaluationEnvironment() : _parent = null;
  EvaluationEnvironment.withParent(this._parent);

  /// Whether the current environment is empty.
  bool get isEmpty {
    // Since we look up variables in enclosing environment, the environment
    // is not empty if its parent is not empty.
    if (_parent != null && !_parent!.isEmpty) return false;
    return _typeVariables.isEmpty && _variables.isEmpty;
  }

  void addTypeParameterValue(TypeParameter parameter, DartType value) {
    assert(!_typeVariables.containsKey(parameter));
    _typeVariables[parameter] = value;
  }

  void addVariableValue(VariableDeclaration variable, Constant value) {
    _variables[variable] = new EvaluationReference(value);
    if (value is UnevaluatedConstant) {
      _unreadUnevaluatedVariables.add(variable);
    }
  }

  Constant? updateVariableValue(VariableDeclaration variable, Constant value) {
    EvaluationReference? reference = _variables[variable];
    if (reference != null) {
      reference.value = value;
      return value;
    }
    return _parent?.updateVariableValue(variable, value);
  }

  Constant? lookupVariable(VariableDeclaration variable) {
    Constant? value = _variables[variable]?.value;
    if (value is UnevaluatedConstant) {
      _unreadUnevaluatedVariables.remove(variable);
    } else if (value == null) {
      return _parent?.lookupVariable(variable);
    }
    return value;
  }

  /// The unevaluated constants of variables that were never read.
  Iterable<UnevaluatedConstant> get unevaluatedUnreadConstants {
    if (_unreadUnevaluatedVariables.isEmpty) return const [];
    return _unreadUnevaluatedVariables.map<UnevaluatedConstant>(
        (VariableDeclaration variable) =>
            _variables[variable]!.value as UnevaluatedConstant);
  }

  DartType substituteType(DartType type) {
    if (_typeVariables.isEmpty) return _parent?.substituteType(type) ?? type;
    final DartType substitutedType = substitute(type, _typeVariables);
    if (identical(substitutedType, type) && _parent != null) {
      // No distinct type created, substitute type in parent.
      return _parent!.substituteType(type);
    }
    return substitutedType;
  }
}

class RedundantFileUriExpressionRemover extends Transformer {
  Uri? currentFileUri = null;

  TreeNode visitFileUriExpression(FileUriExpression node) {
    if (node.fileUri == currentFileUri) {
      return node.expression.accept(this);
    } else {
      Uri? oldFileUri = currentFileUri;
      currentFileUri = node.fileUri;
      node.expression = transform(node.expression)..parent = node;
      currentFileUri = oldFileUri;
      return node;
    }
  }
}

/// Location that stores a value in the [ConstantEvaluator].
class EvaluationReference {
  Constant value;

  EvaluationReference(this.value);
}

/// Represents a status for statement execution.
abstract class ExecutionStatus {
  const ExecutionStatus();
}

/// Status that the statement completed execution successfully.
class ProceedStatus extends ExecutionStatus {
  const ProceedStatus();
}

/// Status that the statement returned a valid [Constant] value.
class ReturnStatus extends ExecutionStatus {
  final Constant? value;
  ReturnStatus(this.value);
}

/// Status with an exception or error that the statement has thrown.
class AbortStatus extends ExecutionStatus {
  final AbortConstant error;
  AbortStatus(this.error);
}

/// Status that the statement breaks out of an enclosing [LabeledStatement].
class BreakStatus extends ExecutionStatus {
  final LabeledStatement target;
  BreakStatus(this.target);
}

/// Mutable lists used within the [ConstantEvaluator].
class MutableListConstant extends ListConstant {
  MutableListConstant(DartType typeArgument, List<Constant> entries)
      : super(typeArgument, entries);

  @override
  String toString() => 'MutableListConstant(${toStringInternal()})';
}

/// An intermediate result that is used for invoking function nodes with their
/// respective environment within the [ConstantEvaluator].
class FunctionValue implements Constant {
  final FunctionNode function;
  final EvaluationEnvironment? environment;

  FunctionValue(this.function, this.environment);

  @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 {
  final TreeNode node;
  final Message message;
  final List<LocatedMessage>? context;

  _AbortDueToErrorConstant(this.node, this.message, {this.context});

  @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();
  }
}

class _AbortDueToInvalidExpressionConstant extends AbortConstant {
  final TreeNode node;
  final String message;

  _AbortDueToInvalidExpressionConstant(this.node, this.message);

  @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();
  }
}

class _AbortDueToThrowConstant extends AbortConstant {
  final TreeNode node;
  final Object throwValue;

  _AbortDueToThrowConstant(this.node, this.throwValue);

  @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 ErrorReporter {
  const ErrorReporter();

  void report(LocatedMessage message, List<LocatedMessage>? context);

  void reportInvalidExpression(InvalidExpression node);
}

class SimpleErrorReporter implements ErrorReporter {
  const SimpleErrorReporter();

  @override
  void report(LocatedMessage message, List<LocatedMessage>? context) {
    _report(message);
    if (context != null) {
      for (LocatedMessage contextMessage in context) {
        _report(contextMessage);
      }
    }
  }

  @override
  void reportInvalidExpression(InvalidExpression node) {
    // Ignored
  }

  void _report(LocatedMessage message) {
    reportMessage(message.uri, message.charOffset, message.message);
  }

  void reportMessage(Uri? uri, int offset, String message) {
    io.exitCode = 42;
    io.stderr.writeln('$uri:$offset Constant evaluation error: $message');
  }
}

class IsInstantiatedVisitor extends DartTypeVisitor<bool> {
  final _availableVariables = new Set<TypeParameter>();

  bool isInstantiated(DartType type) {
    return type.accept(this);
  }

  @override
  bool defaultDartType(DartType node) {
    // Probably unreachable.
    throw 'A visitor method seems to be unimplemented!';
  }

  @override
  bool visitInvalidType(InvalidType node) => true;

  @override
  bool visitDynamicType(DynamicType node) => true;

  @override
  bool visitVoidType(VoidType node) => true;

  @override
  bool visitNullType(NullType node) => true;

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return _availableVariables.contains(node.parameter);
  }

  @override
  bool visitInterfaceType(InterfaceType node) {
    return node.typeArguments
        .every((DartType typeArgument) => typeArgument.accept(this));
  }

  @override
  bool visitFutureOrType(FutureOrType node) {
    return node.typeArgument.accept(this);
  }

  @override
  bool visitFunctionType(FunctionType node) {
    final List<TypeParameter> parameters = node.typeParameters;
    _availableVariables.addAll(parameters);
    final bool result = node.returnType.accept(this) &&
        node.positionalParameters.every((p) => p.accept(this)) &&
        node.namedParameters.every((p) => p.type.accept(this));
    _availableVariables.removeAll(parameters);
    return result;
  }

  @override
  bool visitTypedefType(TypedefType node) {
    // Probably unreachable.
    return node.unalias.accept(this);
  }

  @override
  bool visitNeverType(NeverType node) => true;
}

bool _isFormalParameter(VariableDeclaration variable) {
  final TreeNode? parent = variable.parent;
  if (parent is FunctionNode) {
    return parent.positionalParameters.contains(variable) ||
        parent.namedParameters.contains(variable);
  }
  return false;
}
