// 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:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart';
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,
        messageConstEvalExternalConstructor,
        messageConstEvalExternalFactory,
        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 enableConstructorTearOff,
    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);
  // ignore: unnecessary_null_comparison
  assert(enableConstructorTearOff != 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,
      enableConstructorTearOff: enableConstructorTearOff);
  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,
    required bool enableConstructorTearOff}) {
  // 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);
  // ignore: unnecessary_null_comparison
  assert(enableConstructorTearOff != null);
  final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
      backend,
      environmentDefines,
      evaluateAnnotations,
      enableTripleShift,
      enableConstFunctions,
      enableConstructorTearOff,
      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,
    {required bool evaluateAnnotations,
    required bool enableTripleShift,
    required bool enableConstFunctions,
    required bool enableConstructorTearOff,
    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);
  // ignore: unnecessary_null_comparison
  assert(enableConstructorTearOff != null);
  final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
      backend,
      environmentDefines,
      evaluateAnnotations,
      enableTripleShift,
      enableConstFunctions,
      enableConstructorTearOff,
      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? visitInstantiationConstant(InstantiationConstant 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 InstantiationConstant(node.tearOffConstant, types);
    }
    return null;
  }

  @override
  Constant? visitStaticTearOffConstant(StaticTearOffConstant 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 enableConstructorTearOff;
  final bool errorOnUnevaluatedConstant;

  ConstantsTransformer(
      this.backend,
      Map<String, String>? environmentDefines,
      this.evaluateAnnotations,
      this.enableTripleShift,
      this.enableConstFunctions,
      this.enableConstructorTearOff,
      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);
      transformRedirectingFactoryList(node.redirectingFactories, 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
  RedirectingFactory visitRedirectingFactory(
      RedirectingFactory 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);
      node.function = transform(node.function)..parent = 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) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitConstructorTearOff(
      ConstructorTearOff node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitRedirectingFactoryTearOff(
      RedirectingFactoryTearOff node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitTypedefTearOff(TypedefTearOff node, TreeNode? removalSentinel) {
    return evaluateAndTransformWithContext(node, node);
  }

  @override
  TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
    Instantiation result =
        super.visitInstantiation(node, removalSentinel) as Instantiation;
    Expression expression = result.expression;
    if (expression is ConstantExpression) {
      if (result.typeArguments.every(isInstantiated)) {
        return evaluateAndTransformWithContext(node, result);
      } else if (enableConstructorTearOff) {
        Constant constant = expression.constant;
        if (constant is TypedefTearOffConstant) {
          Substitution substitution =
              Substitution.fromPairs(constant.parameters, node.typeArguments);
          return new Instantiation(
              new ConstantExpression(constant.tearOffConstant,
                  constant.tearOffConstant.getType(_staticTypeContext!))
                ..fileOffset = expression.fileOffset,
              constant.types.map(substitution.substituteType).toList());
        } else {
          LoweredTypedefTearOff? loweredTypedefTearOff =
              LoweredTypedefTearOff.fromConstant(constant);
          if (loweredTypedefTearOff != null) {
            Constant tearOffConstant = constantEvaluator
                .canonicalize(loweredTypedefTearOff.targetTearOffConstant);
            Substitution substitution = Substitution.fromPairs(
                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
                node.typeArguments);
            return new Instantiation(
                new ConstantExpression(tearOffConstant,
                    tearOffConstant.getType(_staticTypeContext!))
                  ..fileOffset = expression.fileOffset,
                loweredTypedefTearOff.typeArguments
                    .map(substitution.substituteType)
                    .toList());
          }
        }
      }
    }
    return node;
  }

  @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 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;
      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 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;

      // For libraries with null safety Symbol constructor accepts arbitrary
      // string as argument.
      if (nameValue is StringConstant &&
          (isNonNullableByDefault || 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}".');
    } else if (constructor.isExternal) {
      return createErrorConstant(node, messageConstEvalExternalConstructor);
    }
    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, caller);
          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, caller);
          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 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 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 StaticTearOffConstant(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 canonicalize(new StaticTearOffConstant(node.target));
  }

  @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) {
        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 _evaluateExpressionInContext(target, variable.initializer!);
  }

  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) {
        if (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.isExternal) {
          return createErrorConstant(node, messageConstEvalExternalFactory);
        }
      }
    } 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.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) {
    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()));
    }
    List<TypeParameter>? typeParameters;
    if (constant is TearOffConstant) {
      Member target = constant.target;
      if (target is Procedure) {
        typeParameters = target.function.typeParameters;
      } else if (target is Constructor) {
        typeParameters = target.enclosingClass.typeParameters;
      }
    } else if (constant is TypedefTearOffConstant) {
      typeParameters = constant.parameters;
    }
    if (typeParameters != null) {
      if (node.typeArguments.length == 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);

        List<DartType> typeArguments = convertTypes(types);
        if (constant is TypedefTearOffConstant) {
          Substitution substitution =
              Substitution.fromPairs(constant.parameters, typeArguments);
          typeArguments =
              constant.types.map(substitution.substituteType).toList();
          constant = constant.tearOffConstant;
        } else {
          LoweredTypedefTearOff? loweredTypedefTearOff =
              LoweredTypedefTearOff.fromConstant(constant);
          if (loweredTypedefTearOff != null) {
            constant =
                canonicalize(loweredTypedefTearOff.targetTearOffConstant);
            Substitution substitution = Substitution.fromPairs(
                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
                node.typeArguments);
            typeArguments = loweredTypedefTearOff.typeArguments
                .map(substitution.substituteType)
                .toList();
          }
        }
        return canonicalize(new InstantiationConstant(constant, typeArguments));
      } else {
        // 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 canonicalize(new ConstructorTearOffConstant(node.target));
  }

  @override
  Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
    return canonicalize(new RedirectingFactoryTearOffConstant(node.target));
  }

  @override
  Constant visitTypedefTearOff(TypedefTearOff node) {
    final Constant constant = _evaluateSubexpression(node.expression);
    if (constant is TearOffConstant) {
      FreshTypeParameters freshTypeParameters =
          getFreshTypeParameters(node.typeParameters);
      List<TypeParameter> typeParameters =
          freshTypeParameters.freshTypeParameters;
      List<DartType> typeArguments = new List<DartType>.generate(
          node.typeArguments.length,
          (int i) => freshTypeParameters.substitute(node.typeArguments[i]),
          growable: false);
      return canonicalize(
          new TypedefTearOffConstant(typeParameters, constant, typeArguments));
    } else {
      // Probably unreachable.
      return createInvalidExpressionConstant(
          node, "Unexpected typedef tearoff target: ${constant}.");
    }
  }

  @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 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 accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference<R>(Visitor<R> v) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
    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 accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference<R>(Visitor<R> v) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
    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 accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference<R>(Visitor<R> v) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
    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 accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference<R>(Visitor<R> v) {
    throw new UnimplementedError();
  }

  @override
  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
    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');
  }
}

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

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;
}
