// Copyright (c) 2020, 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 file implements the AST of a Dart-like language suitable for testing
/// flow analysis.  Callers may use the top level methods in this file to create
/// AST nodes and then feed them to [Harness.run] to run them through flow
/// analysis testing.
library;

import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'
    show
        CascadePropertyTarget,
        ExpressionInfo,
        ExpressionPropertyTarget,
        FlowAnalysis,
        PropertyTarget,
        SuperPropertyTarget,
        ThisPropertyTarget;
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis_operations.dart';
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
import 'package:_fe_analyzer_shared/src/type_inference/null_shorting.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
    hide MapPatternEntry, RecordPatternField;
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_constraint.dart';
import 'package:_fe_analyzer_shared/src/type_inference/variable_bindings.dart';
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:test/test.dart';

import 'mini_ir.dart';
import 'mini_type_constraint_gatherer.dart';
import 'mini_types.dart';

final RegExp _locationRegExp = RegExp(
  '(file:)?[a-zA-Z0-9_./]+.dart:[0-9]+:[0-9]+',
);

SwitchHeadDefault get default_ =>
    SwitchHeadDefault._(location: computeLocation());

ConstExpression get nullLiteral =>
    new NullLiteral._(location: computeLocation());

Expression get this_ => new This._(location: computeLocation());

Statement assert_(ProtoExpression condition, [ProtoExpression? message]) {
  var location = computeLocation();
  return new Assert._(
    condition.asExpression(location: location),
    message?.asExpression(location: location),
    location: location,
  );
}

Statement block(List<ProtoStatement> statements) =>
    new Block._(statements, location: computeLocation());

Expression booleanLiteral(bool value) =>
    BooleanLiteral._(value, location: computeLocation());

Statement break_([Label? target]) =>
    new Break(target, location: computeLocation());

/// Creates a pseudo-expression whose function is to verify that flow analysis
/// considers [variable]'s assigned state to be [expectedAssignedState].
Expression checkAssigned(Var variable, bool expectedAssignedState) =>
    new CheckAssigned._(
      variable,
      expectedAssignedState,
      location: computeLocation(),
    );

/// Creates a pseudo-expression whose function is to verify that flow analysis
/// considers [promotable] to be un-promoted.
Expression checkNotPromoted(Promotable promotable) =>
    new CheckPromoted._(promotable, null, location: computeLocation());

/// Creates a pseudo-expression whose function is to verify that flow analysis
/// considers [promotable]'s assigned state to be promoted to [expectedTypeStr].
Expression checkPromoted(Promotable promotable, String? expectedTypeStr) =>
    new CheckPromoted._(
      promotable,
      expectedTypeStr,
      location: computeLocation(),
    );

/// Creates a pseudo-expression whose function is to verify that flow analysis
/// considers the current location's reachability state to be
/// [expectedReachable].
Expression checkReachable(bool expectedReachable) =>
    new CheckReachable(expectedReachable, location: computeLocation());

/// Creates a pseudo-expression whose function is to verify that flow analysis
/// considers [variable]'s unassigned state to be [expectedUnassignedState].
Expression checkUnassigned(Var variable, bool expectedUnassignedState) =>
    new CheckUnassigned._(
      variable,
      expectedUnassignedState,
      location: computeLocation(),
    );

/// Computes a "location" string using `StackTrace.current` to find the source
/// location of the caller's caller.
///
/// Note: this is highly dependent on the behavior of VM stack traces.  This
/// won't work in code compiled with dart2js for example.  That's fine, though,
/// since we only run these tests under the VM.
String computeLocation() {
  var callStack = StackTrace.current.toString().split('\n');
  assert(callStack[0].contains('mini_ast.dart'));
  assert(callStack[1].contains('mini_ast.dart'));

  String stackLine;
  if (callStack[3].contains('joinPatternVariables')) {
    stackLine = callStack[3];
  } else {
    stackLine = callStack[2];
    assert(
      stackLine.contains('type_inference_test.dart') ||
          stackLine.contains('flow_analysis_test.dart') ||
          stackLine.contains('type_constraint_gatherer_test.dart'),
      'Unexpected file: $stackLine',
    );
  }

  var match = _locationRegExp.firstMatch(stackLine);
  if (match == null) {
    throw AssertionError(
      '_locationRegExp failed to match $stackLine in $callStack',
    );
  }
  return match.group(0)!;
}

Statement continue_([Label? target]) =>
    new Continue._(target, location: computeLocation());

Statement declare(
  Var variable, {
  bool isLate = false,
  bool isFinal = false,
  String? type,
  ProtoExpression? initializer,
  String? expectInferredType,
}) {
  var location = computeLocation();
  return new VariableDeclaration._(
    variable: variable,
    isLate: isLate,
    isFinal: isFinal,
    declaredType: type == null ? null : Type(type),
    initializer: initializer?.asExpression(location: location),
    expectInferredType: expectInferredType,
    location: location,
  );
}

Statement do_(List<ProtoStatement> body, ProtoExpression condition) {
  var location = computeLocation();
  return Do._(
    Block._(body, location: location),
    condition.asExpression(location: location),
    location: location,
  );
}

Expression dotShorthandHead(String name) =>
    new DotShorthandHead._(name, location: computeLocation());

/// Creates a pseudo-expression having type [typeStr] that otherwise has no
/// effect on flow analysis.
ConstExpression expr(String typeStr) =>
    new PlaceholderExpression._(new Type(typeStr), location: computeLocation());

/// Creates a conventional `for` statement.  Optional boolean [forCollection]
/// indicates that this `for` statement is actually a collection element, so
/// `null` should be passed to [FlowAnalysis.for_bodyBegin].
Statement for_(
  ProtoStatement? initializer,
  ProtoExpression? condition,
  ProtoExpression? updater,
  List<ProtoStatement> body, {
  bool forCollection = false,
}) {
  var location = computeLocation();
  return new For._(
    initializer?.asStatement(location: location),
    condition?.asExpression(location: location),
    updater?.asExpression(location: location),
    Block._(body, location: location),
    forCollection,
    location: location,
  );
}

/// Creates a "for each" statement where the identifier being assigned to by the
/// iteration is not a local variable.
///
/// This models code like:
///     var x; // Top level variable
///     f(Iterable iterable) {
///       for (x in iterable) { ... }
///     }
Statement forEachWithNonVariable(
  ProtoExpression iterable,
  List<ProtoStatement> body,
) {
  var location = computeLocation();
  return new ForEach._(
    null,
    iterable.asExpression(location: location),
    Block._(body, location: location),
    false,
    location: location,
  );
}

/// Creates a "for each" statement where the identifier being assigned to by the
/// iteration is a variable that is being declared by the "for each" statement.
///
/// This models code like:
///     f(Iterable iterable) {
///       for (var x in iterable) { ... }
///     }
Statement forEachWithVariableDecl(
  Var variable,
  ProtoExpression iterable,
  List<ProtoStatement> body,
) {
  var location = computeLocation();
  return new ForEach._(
    variable,
    iterable.asExpression(location: location),
    block(body),
    true,
    location: location,
  );
}

/// Creates a "for each" statement where the identifier being assigned to by the
/// iteration is a local variable that is declared elsewhere in the function.
///
/// This models code like:
///     f(Iterable iterable) {
///       var x;
///       for (x in iterable) { ... }
///     }
Statement forEachWithVariableSet(
  Var variable,
  ProtoExpression iterable,
  List<ProtoStatement> body,
) {
  var location = computeLocation();
  return new ForEach._(
    variable,
    iterable.asExpression(location: location),
    Block._(body, location: location),
    false,
    location: location,
  );
}

Statement if_(
  ProtoExpression condition,
  List<ProtoStatement> ifTrue, [
  List<ProtoStatement>? ifFalse,
]) {
  var location = computeLocation();
  return new If._(
    condition.asExpression(location: location),
    Block._(ifTrue, location: location),
    ifFalse == null ? null : Block._(ifFalse, location: location),
    location: location,
  );
}

Statement ifCase(
  ProtoExpression expression,
  PossiblyGuardedPattern pattern,
  List<ProtoStatement> ifTrue, [
  List<ProtoStatement>? ifFalse,
]) {
  var location = computeLocation();
  var guardedPattern = pattern._asGuardedPattern;
  return IfCase(
    expression.asExpression(location: location),
    guardedPattern.pattern,
    guardedPattern.guard,
    Block._(ifTrue, location: location),
    ifFalse != null ? Block._(ifFalse, location: location) : null,
    location: location,
  );
}

CollectionElement ifCaseElement(
  ProtoExpression expression,
  PossiblyGuardedPattern pattern,
  ProtoCollectionElement ifTrue, [
  ProtoCollectionElement? ifFalse,
]) {
  var location = computeLocation();
  var guardedPattern = pattern._asGuardedPattern;
  return new IfCaseElement(
    expression.asExpression(location: location),
    guardedPattern.pattern,
    guardedPattern.guard,
    ifTrue.asCollectionElement(location: location),
    ifFalse?.asCollectionElement(location: location),
    location: location,
  );
}

CollectionElement ifElement(
  ProtoExpression condition,
  ProtoCollectionElement ifTrue, [
  ProtoCollectionElement? ifFalse,
]) {
  var location = computeLocation();
  return new IfElement._(
    condition.asExpression(location: location),
    ifTrue.asCollectionElement(location: location),
    ifFalse?.asCollectionElement(location: location),
    location: location,
  );
}

ConstExpression intLiteral(int value, {bool? expectConversionToDouble}) =>
    new IntLiteral(
      value,
      expectConversionToDouble: expectConversionToDouble,
      location: computeLocation(),
    );

/// Creates a list literal containing the given [elements].
///
/// [elementType] is the explicit type argument of the list literal.
/// TODO(paulberry): support list literals with an inferred type argument.
Expression listLiteral(
  List<ProtoCollectionElement> elements, {
  required String elementType,
}) {
  var location = computeLocation();
  return ListLiteral._(
    [
      for (var element in elements)
        element.asCollectionElement(location: location),
    ],
    Type(elementType),
    location: location,
  );
}

Pattern listPattern(List<ListPatternElement> elements, {String? elementType}) =>
    ListPattern._(
      elementType == null ? null : Type(elementType),
      elements,
      location: computeLocation(),
    );

Expression localFunction(List<ProtoStatement> body) {
  var location = computeLocation();
  return LocalFunction._(Block._(body, location: location), location: location);
}

/// Creates a map entry containing the given [key] and [value] subexpressions.
CollectionElement mapEntry(
  ProtoExpression key,
  ProtoExpression value, {
  bool isKeyNullAware = false,
}) {
  var location = computeLocation();
  return MapEntry._(
    key.asExpression(location: location),
    value.asExpression(location: location),
    isKeyNullAware: isKeyNullAware,
    location: location,
  );
}

/// Creates a map literal containing the given [elements].
///
/// [keyType] and [valueType] are the explicit type arguments of the map
/// literal. TODO(paulberry): support map literals with inferred type arguments.
Expression mapLiteral(
  List<ProtoCollectionElement> elements, {
  required String keyType,
  required String valueType,
}) {
  var location = computeLocation();
  return MapLiteral._(
    [
      for (var element in elements)
        element.asCollectionElement(location: location),
    ],
    Type(keyType),
    Type(valueType),
    location: location,
  );
}

Pattern mapPattern(
  List<MapPatternElement> elements, {
  String? keyType,
  String? valueType,
}) {
  var location = computeLocation();
  return MapPattern._(
    keyType == null && valueType == null
        ? null
        : (keyType: Type(keyType!), valueType: Type(valueType!)),
    elements,
    location: location,
  );
}

MapPatternElement mapPatternEntry(ProtoExpression key, Pattern value) {
  var location = computeLocation();
  return MapPatternEntry._(
    key.asExpression(location: location),
    value,
    location: location,
  );
}

Pattern mapPatternWithTypeArguments({
  required String keyType,
  required String valueType,
  required List<MapPatternElement> elements,
}) {
  var location = computeLocation();
  return MapPattern._(
    (keyType: Type(keyType), valueType: Type(valueType)),
    elements,
    location: location,
  );
}

Pattern objectPattern({
  required String requiredType,
  required List<RecordPatternField> fields,
}) {
  var parsedType = Type(requiredType);
  if (parsedType is! PrimaryType || parsedType.isQuestionType) {
    fail('Expected a primary type, got $parsedType');
  }
  return ObjectPattern._(
    requiredType: parsedType,
    fields: fields,
    location: computeLocation(),
  );
}

/// Creates a "pattern-for-in" statement.
///
/// This models code like:
///     void f(Iterable<(int, String)> iterable) {
///       for (var (a, b) in iterable) { ... }
///     }
Statement patternForIn(
  Pattern pattern,
  ProtoExpression expression,
  List<ProtoStatement> body, {
  bool hasAwait = false,
}) {
  var location = computeLocation();
  return new PatternForIn(
    pattern,
    expression.asExpression(location: location),
    Block._(body, location: location),
    hasAwait: hasAwait,
    location: location,
  );
}

/// Creates a "pattern-for-in" element.
///
/// This models code like:
///     void f(Iterable<(int, String)> iterable) {
///       [for (var (a, b) in iterable) '$a $b']
///     }
CollectionElement patternForInElement(
  Pattern pattern,
  ProtoExpression expression,
  ProtoCollectionElement body, {
  bool hasAwait = false,
}) {
  var location = computeLocation();
  return new PatternForInElement(
    pattern,
    expression.asExpression(location: location),
    body.asCollectionElement(location: location),
    hasAwait: hasAwait,
    location: location,
  );
}

Statement patternVariableDeclaration(
  Pattern pattern,
  ProtoExpression initializer, {
  bool isFinal = false,
}) {
  var location = computeLocation();
  return new PatternVariableDeclaration._(
    pattern,
    initializer.asExpression(location: location),
    isFinal: isFinal,
    location: location,
  );
}

Pattern recordPattern(List<RecordPatternField> fields) =>
    RecordPattern._(fields, location: computeLocation());

Pattern relationalPattern(
  String operator,
  ProtoExpression operand, {
  String? errorId,
}) {
  var location = computeLocation();
  var result = RelationalPattern._(
    operator,
    operand.asExpression(location: location),
    location: location,
  );
  if (errorId != null) {
    result.errorId = errorId;
  }
  return result;
}

/// Creates a "rest" pattern with optional [subPattern], for use in a list
/// pattern.
///
/// Although using a rest pattern inside a map pattern is an error, it's allowed
/// syntactically (since this leads to better error recovery). To facilitate
/// testing of the error recovery logic, the returned type ([RestPattern]) may
/// be used were a [MapPatternElement] is expected.
RestPattern restPattern([Pattern? subPattern]) =>
    RestPattern._(subPattern, location: computeLocation());

Statement return_() => new Return._(location: computeLocation());

/// Models a call to a generic Dart function that takes two arguments and
/// returns the second argument; in other words, a function defined this way:
///
///     T second(dynamic x, T y) => y;
///
/// This can be useful in situations where a test needs to verify certain
/// properties, or establish certain preconditions, before the analysis reaches
/// a certain subexpression.
Expression second(ProtoExpression first, ProtoExpression second) {
  var location = computeLocation();
  return Second._(
    first.asExpression(location: location),
    second.asExpression(location: location),
    location: location,
  );
}

PromotableLValue superProperty(String name) => new ThisOrSuperProperty._(
  name,
  location: computeLocation(),
  isSuperAccess: true,
);

Statement switch_(
  ProtoExpression expression,
  List<SwitchStatementMember> cases, {
  bool? isLegacyExhaustive,
  bool? expectHasDefault,
  bool? expectIsExhaustive,
  bool? expectLastCaseTerminates,
  bool? expectRequiresExhaustivenessValidation,
  String? expectScrutineeType,
}) {
  var location = computeLocation();
  return new SwitchStatement(
    expression.asExpression(location: location),
    cases,
    isLegacyExhaustive,
    location: location,
    expectHasDefault: expectHasDefault,
    expectIsExhaustive: expectIsExhaustive,
    expectLastCaseTerminates: expectLastCaseTerminates,
    expectRequiresExhaustivenessValidation:
        expectRequiresExhaustivenessValidation,
    expectScrutineeType: expectScrutineeType,
  );
}

Expression switchExpr(ProtoExpression expression, List<ExpressionCase> cases) {
  var location = computeLocation();
  return new SwitchExpression._(
    expression.asExpression(location: location),
    cases,
    location: location,
  );
}

SwitchStatementMember switchStatementMember(
  List<ProtoSwitchHead> cases,
  List<ProtoStatement> body, {
  bool hasLabels = false,
}) {
  var location = computeLocation();
  return SwitchStatementMember._(
    [for (var case_ in cases) case_.asSwitchHead],
    Block._(body, location: location),
    hasLabels: hasLabels,
    location: computeLocation(),
  );
}

PromotableLValue thisProperty(String name) => new ThisOrSuperProperty._(
  name,
  location: computeLocation(),
  isSuperAccess: false,
);

Expression throw_(ProtoExpression operand) {
  var location = computeLocation();
  return new Throw._(
    operand.asExpression(location: location),
    location: location,
  );
}

TryBuilder try_(List<ProtoStatement> body) {
  var location = computeLocation();
  return new TryStatementImpl(
    Block._(body, location: location),
    [],
    null,
    location: location,
  );
}

Statement while_(ProtoExpression condition, List<ProtoStatement> body) {
  var location = computeLocation();
  return new While._(
    condition.asExpression(location: location),
    Block._(body, location: location),
    location: location,
  );
}

Pattern wildcard({String? type, String? expectInferredType}) {
  return WildcardPattern._(
    declaredType: type == null ? null : Type(type),
    expectInferredType: expectInferredType,
    location: computeLocation(),
  );
}

typedef SharedMatchContext =
    shared.MatchContext<Node, Expression, Pattern, SharedTypeView, Var>;

typedef SharedRecordPatternField = shared.RecordPatternField<Node, Pattern>;

class As extends Expression {
  final Expression target;
  final Type type;

  As._(this.target, this.type, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    target.preVisit(visitor);
  }

  @override
  String toString() => '$target as $type';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeTypeCast(this, target, type);
  }
}

class Assert extends Statement {
  final Expression condition;
  final Expression? message;

  Assert._(this.condition, this.message, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    condition.preVisit(visitor);
    message?.preVisit(visitor);
  }

  @override
  String toString() =>
      'assert($condition${message == null ? '' : ', $message'});';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeAssertStatement(this, condition, message);
    h.irBuilder.apply(
      'assert',
      [Kind.expression, Kind.expression],
      Kind.statement,
      location: location,
    );
  }
}

class Block extends Statement {
  final List<Statement> statements;

  Block._(List<ProtoStatement> statements, {required super.location})
    : statements = [
        for (var s in statements) s.asStatement(location: location),
      ];

  @override
  void preVisit(PreVisitor visitor) {
    for (var statement in statements) {
      statement.preVisit(visitor);
    }
  }

  @override
  String toString() =>
      statements.isEmpty ? '{}' : '{ ${statements.join(' ')} }';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeBlock(statements);
    h.irBuilder.apply(
      'block',
      List.filled(statements.length, Kind.statement),
      Kind.statement,
      location: location,
    );
  }
}

class BooleanLiteral extends Expression {
  final bool value;

  BooleanLiteral._(this.value, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => '$value';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var type = h.typeAnalyzer.analyzeBoolLiteral(this, value);
    h.irBuilder.atom('$value', Kind.expression, location: location);
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }
}

/// Normal implementation of [Label].
class BoundLabel extends Label {
  final String name;

  Statement? _binding;

  BoundLabel._(this.name) : super._(location: computeLocation());

  @override
  Statement thenStmt(Statement statement) {
    if (statement is! LabeledStatement) {
      statement = LabeledStatement._(statement, location: computeLocation());
    }
    statement.labels.insert(0, this);
    _binding = statement;
    return statement;
  }

  @override
  String toString() => name;

  @override
  Statement? _getBinding() {
    var binding = _binding;
    if (binding == null) {
      fail("Unbound label $name");
    }
    return binding;
  }
}

class Break extends Statement {
  final Label? target;

  Break(this.target, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'break;';

  @override
  void visit(Harness h) {
    var target = this.target;
    h.typeAnalyzer.analyzeBreakStatement(
      target == null
          ? h.typeAnalyzer._currentBreakTarget
          : target._getBinding(),
    );
    h.irBuilder.apply('break', [], Kind.statement, location: location);
  }
}

/// Representation of a cascade expression in the pseudo-Dart language used for
/// flow analysis testing.
class Cascade extends Expression {
  /// The expression appearing before the first `..` (or `?..`).
  final Expression target;

  /// List of the cascade sections. Each cascade section is an ordinary
  /// expression, built around a [Property] or [InvokeMethod] expression whose
  /// target is a [CascadePlaceholder]. See [CascadePlaceholder] for more
  /// information.
  final List<Expression> sections;

  /// Indicates whether the cascade is null-aware (i.e. its first section is
  /// preceded by `?..` instead of `..`).
  final bool isNullAware;

  Cascade._(
    this.target,
    this.sections, {
    required this.isNullAware,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    target.preVisit(visitor);
    for (var section in sections) {
      section.preVisit(visitor);
    }
  }

  @override
  String toString() {
    return [target, if (isNullAware) '?', ...sections].join('');
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    // Form the IR for evaluating the LHS
    var targetType = h.typeAnalyzer.analyzeExpression(target, schema);
    var previousCascadeTargetIR = h.typeAnalyzer._currentCascadeTargetIR;
    var previousCascadeType = h.typeAnalyzer._currentCascadeTargetType;
    // Create a let-variable that will be initialized to the value of the LHS
    var targetTmp =
        h.typeAnalyzer._currentCascadeTargetIR = h.irBuilder.allocateTmp(
          location: location,
        );
    h.typeAnalyzer._currentCascadeTargetType = h.flow
        .cascadeExpression_afterTarget(
          target,
          targetType,
          isNullAware: isNullAware,
        );
    if (isNullAware) {
      h.flow.nullAwareAccess_rightBegin(target, targetType);
      // Push `targetTmp == null` and `targetTmp` on the IR builder stack,
      // because they'll be needed later to form the conditional expression that
      // does the null-aware guarding.
      h.irBuilder.readTmp(targetTmp, location: location);
      h.irBuilder.atom('null', Kind.expression, location: location);
      h.irBuilder.apply(
        '==',
        [Kind.expression, Kind.expression],
        Kind.expression,
        location: location,
      );
      h.irBuilder.readTmp(targetTmp, location: location);
    }
    // Form the IR for evaluating each section
    List<MiniIRTmp> sectionTmps = [];
    for (var section in sections) {
      h.typeAnalyzer.analyzeExpression(section, h.operations.unknownType);
      // Create a let-variable that will be initialized to the value of the
      // section (which will be discarded)
      sectionTmps.add(h.irBuilder.allocateTmp(location: location));
    }
    // For the final IR, `let targetTmp = target in let section1Tmp = section1
    // in section2Tmp = section2 ... in targetTmp`, or, for null-aware cascades,
    // `let targetTmp = target in targetTmp == null ? targetTmp : let
    // section1Tmp = section1 in section2Tmp = section2 ... in targetTmp`.
    h.irBuilder.readTmp(targetTmp, location: location);
    for (int i = sectionTmps.length; i-- > 0;) {
      h.irBuilder.let(sectionTmps[i], location: location);
    }
    if (isNullAware) {
      h.irBuilder.apply(
        'if',
        [Kind.expression, Kind.expression, Kind.expression],
        Kind.expression,
        location: location,
      );
      h.flow.nullAwareAccess_end();
    }
    h.irBuilder.let(targetTmp, location: location);
    h.flow.cascadeExpression_end(this);
    h.typeAnalyzer._currentCascadeTargetIR = previousCascadeTargetIR;
    h.typeAnalyzer._currentCascadeTargetType = previousCascadeType;
    return ExpressionTypeAnalysisResult(type: targetType);
  }
}

/// Representation of the implicit reference to a cascade target in a cascade
/// section, in the pseudo-Dart language used for flow analysis testing.
///
/// For example, in the cascade expression `x..f()`, the cascade section `..f()`
/// is represented as an [InvokeMethod] expression whose `target` is a
/// [CascadePlaceholder].
class CascadePlaceholder extends Expression {
  CascadePlaceholder._({required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() {
    // We use an empty string as the string representation of a cascade
    // placeholder. This ensures that in a cascade expression like `x..f()`, the
    // cascade section will have the string representation `..f()`.
    return '.';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    h.irBuilder.readTmp(
      h.typeAnalyzer._currentCascadeTargetIR!,
      location: location,
    );
    return ExpressionTypeAnalysisResult(
      type: h.typeAnalyzer._currentCascadeTargetType!,
    );
  }
}

class CastPattern extends Pattern {
  final Pattern inner;

  final Type type;

  CastPattern(this.inner, this.type, {required super.location}) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeCastPatternSchema();

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    inner.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeCastPattern(
      context: context,
      pattern: this,
      innerPattern: inner,
      requiredType: SharedTypeView(type),
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(type.type, Kind.type, location: location);
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'castPattern',
      [Kind.pattern, Kind.type, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) =>
      '${inner._debugString(needsKeywordOrType: needsKeywordOrType)} as '
      '${type.type}';
}

/// Representation of a single catch clause in a try/catch statement.  Use
/// [TryBuilder.catch_] to create instances of this class.
class CatchClause {
  final Statement body;
  final Var? exception;
  final Var? stackTrace;

  CatchClause._(this.body, this.exception, this.stackTrace);

  @override
  String toString() {
    String initialPart;
    if (stackTrace != null) {
      initialPart = 'catch (${exception!.name}, ${stackTrace!.name})';
    } else if (exception != null) {
      initialPart = 'catch (${exception!.name})';
    } else {
      initialPart = 'on ...';
    }
    return '$initialPart $body';
  }

  void _preVisit(PreVisitor visitor) {
    body.preVisit(visitor);
  }
}

class CheckAssigned extends Expression {
  final Var variable;
  final bool expectedAssignedState;

  CheckAssigned._(
    this.variable,
    this.expectedAssignedState, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() {
    var verb = expectedAssignedState ? 'is' : 'is not';
    return 'check $variable $verb definitely assigned;';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    expect(
      h.flow.isAssigned(variable),
      expectedAssignedState,
      reason: 'at $location',
    );
    h.irBuilder.atom('null', Kind.expression, location: location);
    return ExpressionTypeAnalysisResult(
      type: SharedTypeView(h.typeAnalyzer.nullType),
    );
  }
}

class CheckPromoted extends Expression {
  final Promotable promotable;
  final String? expectedTypeStr;

  CheckPromoted._(
    this.promotable,
    this.expectedTypeStr, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    promotable.preVisit(visitor);
  }

  @override
  String toString() {
    var predicate =
        expectedTypeStr == null
            ? 'not promoted'
            : 'promoted to $expectedTypeStr';
    return 'check $promotable $predicate;';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var promotedType = promotable._getPromotedType(h);
    expect(promotedType?.type, expectedTypeStr, reason: 'at $location');
    return ExpressionTypeAnalysisResult(
      type: SharedTypeView(NullType.instance),
    );
  }
}

class CheckReachable extends Expression {
  final bool expectedReachable;

  CheckReachable(this.expectedReachable, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'check reachable';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    expect(h.flow.isReachable, expectedReachable, reason: 'at $location');
    h.irBuilder.atom('null', Kind.expression, location: location);
    return new ExpressionTypeAnalysisResult(
      type: SharedTypeView(NullType.instance),
    );
  }
}

class CheckUnassigned extends Expression {
  final Var variable;
  final bool expectedUnassignedState;

  CheckUnassigned._(
    this.variable,
    this.expectedUnassignedState, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() {
    var verb = expectedUnassignedState ? 'is' : 'is not';
    return 'check $variable $verb definitely unassigned;';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    expect(
      h.flow.isUnassigned(variable),
      expectedUnassignedState,
      reason: 'at $location',
    );
    h.irBuilder.atom('null', Kind.expression, location: location);
    return ExpressionTypeAnalysisResult(
      type: SharedTypeView(h.typeAnalyzer.nullType),
    );
  }
}

/// Representation of a collection element in the pseudo-Dart language used for
/// type analysis testing.
abstract class CollectionElement extends Node
    with ProtoCollectionElement<CollectionElement> {
  /// If non-null, the expected IR that should be produced when this collection
  /// element is analyzed.
  String? _expectedIR;

  CollectionElement({required super.location}) : super._();

  @override
  CollectionElement asCollectionElement({required String location}) => this;

  @override
  CollectionElement checkIR(String expectedIR) {
    _expectedIR = expectedIR;
    return this;
  }

  void preVisit(PreVisitor visitor);

  void visit(Harness h, CollectionElementContext context);
}

abstract class CollectionElementContext {}

class CollectionElementContextMapEntry extends CollectionElementContext {
  final Type keyType;
  final Type valueType;

  CollectionElementContextMapEntry._(this.keyType, this.valueType);
}

class CollectionElementContextType extends CollectionElementContext {
  final SharedTypeSchemaView elementTypeSchema;

  CollectionElementContextType._(this.elementTypeSchema);
}

class Conditional extends Expression {
  final Expression condition;
  final Expression ifTrue;
  final Expression ifFalse;

  Conditional._(
    this.condition,
    this.ifTrue,
    this.ifFalse, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    condition.preVisit(visitor);
    visitor._assignedVariables.beginNode();
    ifTrue.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
    ifFalse.preVisit(visitor);
  }

  @override
  String toString() => '$condition ? $ifTrue : $ifFalse';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeConditionalExpression(
      this,
      condition,
      ifTrue,
      ifFalse,
    );
    h.irBuilder.apply(
      'if',
      [Kind.expression, Kind.expression, Kind.expression],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

class ConstantPattern extends Pattern {
  final Expression constant;

  ConstantPattern(this.constant, {required super.location}) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeConstantPatternSchema();

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    constant.preVisit(visitor);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeConstantPattern(
      context,
      this,
      constant,
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'const',
      [Kind.expression, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  _debugString({required bool needsKeywordOrType}) => constant.toString();
}

/// Common interface shared by constructs that represent constant expressions,
/// in the pseudo-Dart language used for flow analysis testing.
abstract class ConstExpression extends Expression {
  ConstExpression._({required super.location});

  /// Converts this expression into a constant pattern.
  Pattern get pattern => ConstantPattern(this, location: computeLocation());
}

class Continue extends Statement {
  final Label? target;

  Continue._(this.target, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'continue;';

  @override
  void visit(Harness h) {
    var target = this.target;
    h.typeAnalyzer.analyzeContinueStatement(
      target == null
          ? h.typeAnalyzer._currentContinueTarget
          : target._getBinding(),
    );
    h.irBuilder.apply('continue', [], Kind.statement, location: location);
  }
}

class Do extends Statement {
  final Statement body;
  final Expression condition;

  Do._(this.body, this.condition, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.beginNode();
    body.preVisit(visitor);
    condition.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() => 'do $body while ($condition);';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeDoLoop(this, body, condition);
    h.irBuilder.apply(
      'do',
      [Kind.statement, Kind.expression],
      Kind.statement,
      location: location,
    );
  }
}

// Represents the entire dot shorthand expression.
// e.g. `.current.errorZone`
class DotShorthand extends Expression {
  final Expression expr;

  DotShorthand._(this.expr, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    expr.preVisit(visitor);
  }

  @override
  String toString() => '$expr';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeDotShorthandExpression(expr, schema);
  }
}

// Represents the head of a dot shorthand.
// e.g. `.zero`
class DotShorthandHead extends Expression {
  final String name;

  DotShorthandHead._(this.name, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => '.$name';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeDotShorthandHeadExpression(this, name, schema);
  }
}

class Equal extends Expression {
  final Expression lhs;
  final Expression rhs;
  final bool isInverted;

  Equal._(this.lhs, this.rhs, this.isInverted, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    lhs.preVisit(visitor);
    rhs.preVisit(visitor);
  }

  @override
  String toString() => '$lhs ${isInverted ? '!=' : '=='} $rhs';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var operatorName = isInverted ? '!=' : '==';
    var result = h.typeAnalyzer.analyzeBinaryExpression(
      this,
      lhs,
      operatorName,
      rhs,
    );
    h.irBuilder.apply(
      operatorName,
      [Kind.expression, Kind.expression],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

/// Representation of an expression in the pseudo-Dart language used for flow
/// analysis testing.  Methods in this class may be used to create more complex
/// expressions based on this one.
abstract class Expression extends Node
    with
        ProtoStatement<Expression>,
        ProtoCollectionElement<Expression>,
        ProtoExpression {
  /// If non-null, the expected IR that should be produced when this expression
  /// is analyzed.
  String? _expectedIR;

  /// If non-null, the expected schema that should be used to analyze this
  /// expression.
  String? _expectedSchema;

  /// If non-null, the expected type that should be produced when this
  /// expression is analyzed.
  String? _expectedType;

  Expression({required super.location}) : super._();

  @override
  Expression asExpression({required String location}) => this;

  void preVisit(PreVisitor visitor);

  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema);
}

/// Representation of a single case clause in a switch expression.  Use
/// [PossiblyGuardedPattern.thenExpr] or [SwitchHead.thenExpr] to create
/// instances of this class.
class ExpressionCase extends Node {
  final GuardedPattern? guardedPattern;
  final Expression expression;

  ExpressionCase._(
    this.guardedPattern,
    this.expression, {
    required super.location,
  }) : super._();

  @override
  String toString() => [
    guardedPattern == null ? 'default' : 'case $guardedPattern',
    ': $expression',
  ].join('');

  void _preVisit(PreVisitor visitor) {
    final guardedPattern = this.guardedPattern;
    if (guardedPattern != null) {
      var variableBinder = _VariableBinder(visitor);
      variableBinder.casePatternStart();
      guardedPattern.pattern.preVisit(
        visitor,
        variableBinder,
        isInAssignment: false,
      );
      guardedPattern.variables = variableBinder.casePatternFinish();
      variableBinder.finish();
    }
    expression.preVisit(visitor);
  }
}

class ExpressionCollectionElement extends CollectionElement {
  final Expression expression;

  ExpressionCollectionElement(this.expression, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    expression.preVisit(visitor);
  }

  @override
  String toString() => '$expression;';

  @override
  void visit(Harness h, CollectionElementContext context) {
    SharedTypeSchemaView typeSchema =
        context is CollectionElementContextType
            ? context.elementTypeSchema
            : h.operations.unknownType;
    h.typeAnalyzer.analyzeExpression(expression, typeSchema);
    h.irBuilder.apply(
      'celt',
      [Kind.expression],
      Kind.collectionElement,
      location: location,
    );
  }
}

class ExpressionInTypeSchema extends Statement {
  final Expression expr;

  final SharedTypeSchemaView typeSchema;

  ExpressionInTypeSchema._(
    this.expr,
    this.typeSchema, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    expr.preVisit(visitor);
  }

  @override
  String toString() => '$expr (in type schema $typeSchema);';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeExpression(expr, typeSchema);
    h.irBuilder.apply(
      'stmt',
      [Kind.expression],
      Kind.statement,
      location: location,
    );
  }
}

class ExpressionStatement extends Statement {
  final Expression expr;

  ExpressionStatement._(this.expr, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    expr.preVisit(visitor);
  }

  @override
  String toString() => '$expr;';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeExpressionStatement(expr);
    h.irBuilder.apply(
      'stmt',
      [Kind.expression],
      Kind.statement,
      location: location,
    );
  }
}

class For extends Statement {
  final Statement? initializer;
  final Expression? condition;
  final Expression? updater;
  final Statement body;
  final bool forCollection;

  For._(
    this.initializer,
    this.condition,
    this.updater,
    this.body,
    this.forCollection, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    initializer?.preVisit(visitor);
    visitor._assignedVariables.beginNode();
    condition?.preVisit(visitor);
    body.preVisit(visitor);
    updater?.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() {
    var buffer = StringBuffer('for (');
    if (initializer == null) {
      buffer.write(';');
    } else {
      buffer.write(initializer);
    }
    if (condition == null) {
      buffer.write(';');
    } else {
      buffer.write(' $condition;');
    }
    if (updater != null) {
      buffer.write(' $updater');
    }
    buffer.write(') $body');
    return buffer.toString();
  }

  @override
  void visit(Harness h) {
    if (initializer != null) {
      h.typeAnalyzer.dispatchStatement(initializer!);
    } else {
      h.typeAnalyzer.handleNoInitializer(this);
    }
    h.flow.for_conditionBegin(this);
    if (condition != null) {
      h.typeAnalyzer.analyzeExpression(condition!, h.operations.unknownType);
    } else {
      h.typeAnalyzer.handleNoCondition(this);
    }
    h.flow.for_bodyBegin(forCollection ? null : this, condition);
    h.typeAnalyzer._visitLoopBody(this, body);
    h.flow.for_updaterBegin();
    if (updater != null) {
      h.typeAnalyzer.analyzeExpression(updater!, h.operations.unknownType);
    } else {
      h.typeAnalyzer.handleNoCondition(this);
    }
    h.flow.for_end();
    h.irBuilder.apply(
      'for',
      [Kind.statement, Kind.expression, Kind.statement, Kind.expression],
      Kind.statement,
      location: location,
    );
  }
}

class ForEach extends Statement {
  final Var? variable;
  final Expression iterable;
  final Statement body;
  final bool declaresVariable;

  ForEach._(
    this.variable,
    this.iterable,
    this.body,
    this.declaresVariable, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    iterable.preVisit(visitor);
    if (variable != null) {
      if (declaresVariable) {
        visitor._assignedVariables.declare(variable!);
      } else {
        visitor._assignedVariables.write(variable!);
      }
    }
    visitor._assignedVariables.beginNode();
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() {
    String declarationPart;
    if (variable == null) {
      declarationPart = '<identifier>';
    } else if (declaresVariable) {
      declarationPart = variable.toString();
    } else {
      declarationPart = variable!.name;
    }
    return 'for ($declarationPart in $iterable) $body';
  }

  @override
  void visit(Harness h) {
    var iteratedType = h._getIteratedType(
      h.typeAnalyzer
          .analyzeExpression(iterable, h.operations.unknownType)
          .unwrapTypeView<Type>(),
    );
    h.flow.forEach_bodyBegin(this);
    var variable = this.variable;
    if (variable != null && !declaresVariable) {
      h.flow.write(this, variable, SharedTypeView(iteratedType), null);
    }
    h.typeAnalyzer._visitLoopBody(this, body);
    h.flow.forEach_end();
    h.irBuilder.apply(
      'forEach',
      [Kind.expression, Kind.statement],
      Kind.statement,
      location: location,
    );
  }
}

class GuardedPattern extends Node with PossiblyGuardedPattern {
  final Pattern pattern;
  late final Map<String, Var> variables;
  final Expression? guard;

  GuardedPattern._({
    required this.pattern,
    required this.guard,
    required super.location,
  }) : super._();

  @override
  GuardedPattern get _asGuardedPattern => this;
}

class Harness {
  static Map<String, Type> _coreMemberTypes = {
    'int.<': Type('bool Function(num)'),
    'int.<=': Type('bool Function(num)'),
    'int.>': Type('bool Function(num)'),
    'int.>=': Type('bool Function(num)'),
    'int.abs': Type('int Function()'),
    'int.isEven': Type('bool'),
    'num.sign': Type('num'),
    'Object.toString': Type('String Function()'),
  };

  final MiniAstOperations operations = MiniAstOperations();

  bool _started = false;

  late final FlowAnalysis<Node, Statement, Expression, Var, SharedTypeView>
  flow;

  bool? _inferenceUpdate3Enabled;

  bool? _inferenceUpdate4Enabled;

  bool? _soundFlowAnalysisEnabled;

  bool? _patternsEnabled;

  Type? _thisType;

  late final Map<String, _PropertyElement?> _members = {
    for (var entry in _coreMemberTypes.entries)
      entry.key: _PropertyElement(
        entry.value,
        entry.key.split('.').last,
        isPromotable: false,
        whyNotPromotable: null,
      ),
  };

  late final typeAnalyzer = _MiniAstTypeAnalyzer(
    this,
    computeTypeAnalyzerOptions(),
  );

  /// Indicates whether initializers of implicitly typed variables should be
  /// accounted for by SSA analysis.  (In an ideal world, they always would be,
  /// but due to https://github.com/dart-lang/language/issues/1785, they weren't
  /// always, and we need to be able to replicate the old behavior when
  /// analyzing old language versions).
  bool _respectImplicitlyTypedVarInitializers = true;

  bool _fieldPromotionEnabled = true;

  bool get inferenceUpdate3Enabled => _inferenceUpdate3Enabled ?? true;

  bool get inferenceUpdate4Enabled => _inferenceUpdate4Enabled ?? true;

  MiniIRBuilder get irBuilder => typeAnalyzer._irBuilder;

  bool get patternsEnabled => _patternsEnabled ?? true;

  bool get soundFlowAnalysisEnabled => _soundFlowAnalysisEnabled ?? true;

  set thisType(String type) {
    assert(!_started);
    _thisType = Type(type);
  }

  /// Updates the harness with a new result for
  /// [MiniAstOperations.downwardInfer].
  void addDownwardInfer({
    required String name,
    required String context,
    required String result,
  }) {
    operations.addDownwardInfer(name: name, context: context, result: result);
  }

  /// Updates the harness so that when an
  /// [TypeAnalyzerOperations.isAlwaysExhaustiveType] query is invoked on type
  /// [type], [isExhaustive] will be returned.
  void addExhaustiveness(String type, bool isExhaustive) {
    operations.addExhaustiveness(type, isExhaustive);
  }

  /// Updates the harness so that when an extension type erasure query is
  /// invoked on type [type], [representation] will be returned.
  void addExtensionTypeErasure(String type, String representation) {
    operations.addExtensionTypeErasure(type, representation);
  }

  void addLub(String type1, String type2, String resultType) {
    operations.addLub(type1, type2, resultType);
  }

  /// Updates the harness so that when member [memberName] is looked up on type
  /// [targetType], a member is found having the given [type].
  ///
  /// If [type] is `null`, then an attempt to look up [memberName] on type
  /// [targetType] should result in `null` (no such member) rather than a test
  /// failure.
  void addMember(
    String targetType,
    String memberName,
    String? type, {
    bool promotable = false,
    PropertyNonPromotabilityReason? whyNotPromotable,
  }) {
    if (promotable) {
      assert(whyNotPromotable == null);
    }
    var query = '$targetType.$memberName';
    if (type == null) {
      if (promotable) {
        fail(
          "It doesn't make sense to specify `promotable: true` "
          "when the type is `null`",
        );
      }
      _members[query] = null;
      return;
    }
    _members[query] = _PropertyElement(
      Type(type),
      memberName,
      isPromotable: promotable,
      whyNotPromotable: whyNotPromotable,
    );
  }

  void addPromotionException(String from, String to, String result) {
    operations.addPromotionException(from, to, result);
  }

  void addSuperInterfaces(
    String className,
    List<Type> Function(List<Type>) template,
  ) {
    operations.addSuperInterfaces(className, template);
  }

  shared.TypeAnalyzerOptions computeTypeAnalyzerOptions() =>
      TypeAnalyzerOptions(
        patternsEnabled: patternsEnabled,
        inferenceUpdate3Enabled: inferenceUpdate3Enabled,
        respectImplicitlyTypedVarInitializers:
            _respectImplicitlyTypedVarInitializers,
        fieldPromotionEnabled: _fieldPromotionEnabled,
        inferenceUpdate4Enabled: inferenceUpdate4Enabled,
        soundFlowAnalysisEnabled: soundFlowAnalysisEnabled,
      );

  void disableFieldPromotion() {
    assert(!_started);
    _fieldPromotionEnabled = false;
  }

  void disableInferenceUpdate3() {
    assert(!_started);
    _inferenceUpdate3Enabled = false;
  }

  void disableInferenceUpdate4() {
    assert(!_started);
    _inferenceUpdate4Enabled = false;
  }

  void disablePatterns() {
    assert(!_started);
    _patternsEnabled = false;
  }

  void disableRespectImplicitlyTypedVarInitializers() {
    assert(!_started);
    _respectImplicitlyTypedVarInitializers = false;
  }

  void disableSoundFlowAnalysis() {
    assert(!_started);
    _soundFlowAnalysisEnabled = false;
  }

  /// Attempts to look up a member named [memberName] in the given [type].  If
  /// a member is found, returns its [_PropertyElement] object; otherwise `null`
  /// is returned.
  ///
  /// If test hasn't been configured in such a way that the result of the query
  /// is known, the test fails.
  _PropertyElement? getMember(Type type, String memberName) {
    var query = '$type.$memberName';
    var member = _members[query];
    // If an explicit map entry was found for this member, return the associated
    // value (even if it is `null`; `null` means the test has been explicitly
    // configured so that the member lookup is supposed to find nothing).
    if (member != null || _members.containsKey(query)) return member;
    switch (memberName) {
      case 'toString':
        // Assume that all types implement `Object.toString`.
        return _members['Object.$memberName']!;
      default:
        // It's legal to look up any member on the type `dynamic`.
        if (type is DynamicType) {
          return null;
        }
        // But an attempt to look up an unknown member on any other type
        // results in a test failure. This is to catch mistakes in unit tests;
        // if the unit test is deliberately trying to exercise a member lookup
        // that should find nothing, please use `addMember` to store an
        // explicit `null` value in the `_members` map.
        fail('Unknown member query: $query');
    }
  }

  /// See [TypeAnalyzer.resolveRelationalPatternOperator].
  RelationalOperatorResolution? resolveRelationalPatternOperator(
    Type matchedValueType,
    String operator,
  ) {
    if (operator == '==' || operator == '!=') {
      return RelationalOperatorResolution(
        kind:
            operator == '=='
                ? RelationalOperatorKind.equals
                : RelationalOperatorKind.notEquals,
        parameterType: SharedTypeView(Type('Object')),
        returnType: SharedTypeView(Type('bool')),
      );
    }
    var member = getMember(matchedValueType, operator);
    if (member == null) return null;
    var memberType = member._type;
    if (memberType is! FunctionType || memberType.isQuestionType) {
      fail(
        '$matchedValueType.operator$operator has type $memberType; '
        'must be a function type',
      );
    }
    if (memberType.positionalParameters.isEmpty) {
      fail(
        '$matchedValueType.operator$operator has type $memberType; '
        'must accept a parameter',
      );
    }
    return RelationalOperatorResolution(
      kind: RelationalOperatorKind.other,
      parameterType: SharedTypeView(memberType.positionalParameters[0]),
      returnType: SharedTypeView(memberType.returnType),
    );
  }

  /// Runs the given [statements] through flow analysis, checking any assertions
  /// they contain.
  void run(
    List<ProtoStatement> statements, {
    bool errorRecoveryOK = false,
    Set<String> expectedErrors = const {},
  }) {
    try {
      _started = true;
      var visitor = PreVisitor(typeAnalyzer.errors);
      var b = Block._(statements, location: computeLocation());
      b.preVisit(visitor);
      flow = FlowAnalysis<Node, Statement, Expression, Var, SharedTypeView>(
        operations,
        visitor._assignedVariables,
        typeAnalyzerOptions: computeTypeAnalyzerOptions(),
      );
      typeAnalyzer.dispatchStatement(b);
      typeAnalyzer.finish();
      expect(typeAnalyzer.errors._accumulatedErrors, expectedErrors);
      var assertInErrorRecoveryStack =
          typeAnalyzer.errors._assertInErrorRecoveryStack;
      if (!errorRecoveryOK && assertInErrorRecoveryStack != null) {
        fail(
          'assertInErrorRecovery called but no errors reported: '
          '$assertInErrorRecoveryStack',
        );
      }
      if (Node._nodesWithUnusedErrorIds.isNotEmpty) {
        var ids = [
          for (var node in Node._nodesWithUnusedErrorIds) node._errorId,
        ].join(', ');
        fail('Unused error ids: $ids');
      }
    } finally {
      Node._nodesWithUnusedErrorIds.clear();
    }
  }

  Type _getIteratedType(Type iterableType) {
    var typeStr = iterableType.type;
    if (typeStr.startsWith('List<') && typeStr.endsWith('>')) {
      return Type(typeStr.substring(5, typeStr.length - 1));
    } else {
      throw UnimplementedError('TODO(paulberry): getIteratedType($typeStr)');
    }
  }
}

class If extends IfBase {
  final Expression condition;

  If._(this.condition, super.ifTrue, super.ifFalse, {required super.location})
    : super._();

  @override
  String get _conditionPartString => condition.toString();

  @override
  void preVisit(PreVisitor visitor) {
    condition.preVisit(visitor);
    super.preVisit(visitor);
  }

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeIfStatement(this, condition, ifTrue, ifFalse);
    h.irBuilder.apply(
      'if',
      [Kind.expression, Kind.statement, Kind.statement],
      Kind.statement,
      location: location,
    );
  }
}

abstract class IfBase extends Statement {
  final Statement ifTrue;
  final Statement? ifFalse;

  IfBase._(this.ifTrue, this.ifFalse, {required super.location});

  String get _conditionPartString;

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.beginNode();
    ifTrue.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
    ifFalse?.preVisit(visitor);
  }

  @override
  String toString() =>
      'if ($_conditionPartString) $ifTrue' +
      (ifFalse == null ? '' : 'else $ifFalse');
}

class IfCase extends IfBase {
  final Expression expression;
  final Pattern pattern;
  final Expression? guard;

  /// These variables are set during pre-visit, and some of them are joins of
  /// pattern variable declarations. We don't know their types until we do
  /// type analysis. So, some of these variables might become unavailable.
  late final Map<String, Var> _candidateVariables;

  IfCase(
    this.expression,
    this.pattern,
    this.guard,
    super.ifTrue,
    super.ifFalse, {
    required super.location,
  }) : super._();

  @override
  String get _conditionPartString => '$expression case $pattern';

  @override
  void preVisit(PreVisitor visitor) {
    expression.preVisit(visitor);
    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    pattern.preVisit(visitor, variableBinder, isInAssignment: false);
    _candidateVariables = variableBinder.casePatternFinish();
    variableBinder.finish();
    guard?.preVisit(visitor);
    super.preVisit(visitor);
  }

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeIfCaseStatement(
      this,
      expression,
      pattern,
      guard,
      ifTrue,
      ifFalse,
      _candidateVariables,
    );
    h.irBuilder.apply(
      'ifCase',
      [
        Kind.expression,
        Kind.pattern,
        Kind.variables,
        Kind.expression,
        Kind.statement,
        Kind.statement,
      ],
      Kind.statement,
      location: location,
    );
  }
}

class IfCaseElement extends IfElementBase {
  final Expression expression;
  final Pattern pattern;
  final Expression? guard;
  late final Map<String, Var> _variables;

  IfCaseElement(
    this.expression,
    this.pattern,
    this.guard,
    super.ifTrue,
    super.ifFalse, {
    required super.location,
  }) : super._();

  @override
  String get _conditionPartString => '$expression case $pattern';

  @override
  void preVisit(PreVisitor visitor) {
    expression.preVisit(visitor);
    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    pattern.preVisit(visitor, variableBinder, isInAssignment: false);
    _variables = variableBinder.casePatternFinish();
    variableBinder.finish();
    guard?.preVisit(visitor);
    super.preVisit(visitor);
  }

  @override
  void visit(Harness h, Object context) {
    h.typeAnalyzer.analyzeIfCaseElement(
      node: this,
      expression: expression,
      pattern: pattern,
      variables: _variables,
      guard: guard,
      ifTrue: ifTrue,
      ifFalse: ifFalse,
      context: context,
    );
    h.irBuilder.apply(
      'if',
      [
        Kind.expression,
        Kind.pattern,
        Kind.expression,
        Kind.collectionElement,
        Kind.collectionElement,
      ],
      Kind.collectionElement,
      names: ['expression', 'pattern', 'guard', 'ifTrue', 'ifFalse'],
      location: location,
    );
  }
}

class IfElement extends IfElementBase {
  final Expression condition;

  IfElement._(
    this.condition,
    super.ifTrue,
    super.ifFalse, {
    required super.location,
  }) : super._();

  @override
  String get _conditionPartString => condition.toString();

  @override
  void preVisit(PreVisitor visitor) {
    condition.preVisit(visitor);
    super.preVisit(visitor);
  }

  @override
  void visit(Harness h, Object context) {
    h.typeAnalyzer.analyzeIfElement(
      node: this,
      condition: condition,
      ifTrue: ifTrue,
      ifFalse: ifFalse,
      context: context,
    );
    h.irBuilder.apply(
      'if',
      [Kind.expression, Kind.collectionElement, Kind.collectionElement],
      Kind.collectionElement,
      location: location,
    );
  }
}

abstract class IfElementBase extends CollectionElement {
  final CollectionElement ifTrue;
  final CollectionElement? ifFalse;

  IfElementBase._(this.ifTrue, this.ifFalse, {required super.location});

  String get _conditionPartString;

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.beginNode();
    ifTrue.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
    ifFalse?.preVisit(visitor);
  }

  @override
  String toString() =>
      'if ($_conditionPartString) $ifTrue' +
      (ifFalse == null ? '' : 'else $ifFalse');
}

class IfNull extends Expression {
  final Expression lhs;
  final Expression rhs;

  IfNull._(this.lhs, this.rhs, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    lhs.preVisit(visitor);
    rhs.preVisit(visitor);
  }

  @override
  String toString() => '$lhs ?? $rhs';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeIfNullExpression(this, lhs, rhs);
    h.irBuilder.apply(
      'ifNull',
      [Kind.expression, Kind.expression],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

class IntLiteral extends ConstExpression {
  final int value;

  /// `true` or `false` if we should assert that int->double conversion either
  /// does, or does not, happen.  `null` if no assertion should be done.
  final bool? expectConversionToDouble;

  IntLiteral(
    this.value, {
    this.expectConversionToDouble,
    required super.location,
  }) : super._();

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => '$value';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeIntLiteral(schema);
    if (expectConversionToDouble != null) {
      expect(result.convertedToDouble, expectConversionToDouble);
    }
    h.irBuilder.atom(
      result.convertedToDouble ? '${value.toDouble()}f' : '$value',
      Kind.expression,
      location: location,
    );
    return result;
  }
}

/// Representation of a method invocation in the pseudo-Dart language used for
/// flow analysis testing.
class InvokeMethod extends Expression {
  // The expression appering before the `.`.
  final Expression target;

  // The name of the method being invoked.
  final String methodName;

  // The arguments being passed to the invocation.
  final List<Expression> arguments;

  final bool isNullAware;

  InvokeMethod._(
    this.target,
    this.methodName,
    this.arguments, {
    required this.isNullAware,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    target.preVisit(visitor);
    for (var argument in arguments) {
      argument.preVisit(visitor);
    }
  }

  @override
  String toString() {
    var q = isNullAware ? '?' : '';
    return '$target$q.$methodName'
        '(${[for (var arg in arguments) arg].join(', ')})';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeMethodInvocation(
      this,
      target is CascadePlaceholder ? null : target,
      methodName,
      arguments,
      isNullAware: isNullAware,
    );
  }
}

class Is extends Expression {
  final Expression target;
  final Type type;
  final bool isInverted;

  Is._(this.target, this.type, this.isInverted, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    target.preVisit(visitor);
  }

  @override
  String toString() => '$target is${isInverted ? '!' : ''} $type';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeTypeTest(
      this,
      target,
      type,
      isInverted: isInverted,
    );
  }
}

abstract class Label extends Node {
  factory Label(String name) = BoundLabel._;

  factory Label.unbound() = UnboundLabel._;

  Label._({required super.location}) : super._();

  Statement thenStmt(Statement statement);

  /// Returns the statement this label has been bound to, or `null` for labels
  /// constructed with [Label.unbound].
  Statement? _getBinding();
}

class LabeledStatement extends Statement {
  final List<Label> labels = [];

  final Statement body;

  LabeledStatement._(this.body, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    body.preVisit(visitor);
  }

  @override
  String toString() => [...labels, body].join(': ');

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeLabeledStatement(this, body);
  }
}

/// Representation of a list literal in the pseudo-Dart language used for flow
/// analysis testing.
class ListLiteral extends Expression {
  final List<CollectionElement> elements;
  final Type elementType;

  ListLiteral._(this.elements, this.elementType, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    for (var element in elements) {
      element.preVisit(visitor);
    }
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    for (var element in elements) {
      h.typeAnalyzer.dispatchCollectionElement(
        element,
        CollectionElementContextType._(SharedTypeSchemaView(elementType)),
      );
    }
    h.irBuilder.apply(
      'list',
      [for (var _ in elements) Kind.collectionElement],
      Kind.expression,
      location: location,
    );
    return ExpressionTypeAnalysisResult(
      type: h.operations.listType(SharedTypeView(elementType)),
    );
  }
}

abstract class ListOrMapPatternElement implements Node {
  ListOrMapPatternElement._();

  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  });

  String _debugString({required bool needsKeywordOrType});
}

class ListPattern extends Pattern {
  final Type? elementType;

  final List<ListPatternElement> elements;

  ListPattern._(this.elementType, this.elements, {required super.location})
    : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeListPatternSchema(
        elementType: elementType?.wrapSharedTypeView(),
        elements: elements,
      );

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    for (var element in elements) {
      element.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
    }
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var listPatternResult = h.typeAnalyzer.analyzeListPattern(
      context,
      this,
      elementType: elementType?.wrapSharedTypeView(),
      elements: elements,
    );
    var matchedType = listPatternResult.matchedValueType.unwrapTypeView<Type>();
    var requiredType = listPatternResult.requiredType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.atom(requiredType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'listPattern',
      [...List.filled(elements.length, Kind.pattern), Kind.type, Kind.type],
      Kind.pattern,
      names: ['matchedType', 'requiredType'],
      location: location,
    );
    return listPatternResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    var elements = [
      for (var element in this.elements)
        element._debugString(needsKeywordOrType: needsKeywordOrType),
    ];
    return '[${elements.join(', ')}]';
  }
}

abstract class ListPatternElement implements ListOrMapPatternElement {}

class LocalFunction extends Expression {
  final Statement body;
  final Type type;

  LocalFunction._(this.body, {String? type, required super.location})
    : type = Type(type ?? 'void Function()');

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.beginNode();
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(
      this,
      isClosureOrLateVariableInitializer: true,
    );
  }

  @override
  String toString() => '() $body';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    h.flow.functionExpression_begin(this);
    h.typeAnalyzer.dispatchStatement(body);
    h.flow.functionExpression_end();
    h.irBuilder.apply(
      'localFunction',
      [Kind.statement],
      Kind.expression,
      location: location,
    );
    return ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }
}

class Logical extends Expression {
  final Expression lhs;
  final Expression rhs;
  final bool isAnd;

  Logical._(this.lhs, this.rhs, {required this.isAnd, required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    lhs.preVisit(visitor);
    visitor._assignedVariables.beginNode();
    rhs.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() => '$lhs ${isAnd ? '&&' : '||'} $rhs';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var operatorName = isAnd ? '&&' : '||';
    var result = h.typeAnalyzer.analyzeBinaryExpression(
      this,
      lhs,
      operatorName,
      rhs,
    );
    h.irBuilder.apply(
      operatorName,
      [Kind.expression, Kind.expression],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

class LogicalAndPattern extends Pattern {
  final Pattern lhs;

  final Pattern rhs;

  LogicalAndPattern._(this.lhs, this.rhs, {required super.location})
    : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeLogicalAndPatternSchema(lhs, rhs);

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    lhs.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
    rhs.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeLogicalAndPattern(
      context,
      this,
      lhs,
      rhs,
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'logicalAndPattern',
      [Kind.pattern, Kind.pattern, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  _debugString({required bool needsKeywordOrType}) => [
    lhs._debugString(needsKeywordOrType: false),
    '&&',
    rhs._debugString(needsKeywordOrType: false),
  ].join(' ');
}

class LogicalOrPattern extends Pattern {
  final Pattern lhs;

  final Pattern rhs;

  LogicalOrPattern(this.lhs, this.rhs, {required super.location}) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeLogicalOrPatternSchema(lhs, rhs);

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    variableBinder.logicalOrPatternStart();
    lhs.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
    variableBinder.logicalOrPatternFinishLeft();
    rhs.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
    variableBinder.logicalOrPatternFinish(this);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeLogicalOrPattern(
      context,
      this,
      lhs,
      rhs,
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'logicalOrPattern',
      [Kind.pattern, Kind.pattern, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  _debugString({required bool needsKeywordOrType}) => [
    lhs._debugString(needsKeywordOrType: false),
    '||',
    rhs._debugString(needsKeywordOrType: false),
  ].join(' ');
}

/// Representation of an expression that can appear on the left hand side of an
/// assignment (or as the target of `++` or `--`).  Methods in this class may be
/// used to create more complex expressions based on this one.
abstract class LValue extends Expression {
  LValue._({required super.location});

  @override
  void preVisit(PreVisitor visitor, {_LValueDisposition disposition});

  /// Creates an expression representing a write to this L-value.
  Expression write(ProtoExpression? value) {
    var location = computeLocation();
    return new Write(
      this,
      value?.asExpression(location: location),
      location: location,
    );
  }

  void _visitPostIncDec(
    Harness h,
    Expression postIncDecExpression,
    Type writtenType,
  );

  void _visitWrite(
    Harness h,
    Expression assignmentExpression,
    Type writtenType,
    Expression? rhs,
  );
}

/// Representation of a map entry in the pseudo-Dart language used for flow
/// analysis testing.
class MapEntry extends CollectionElement {
  final Expression key;
  final Expression value;
  final bool isKeyNullAware;

  MapEntry._(
    this.key,
    this.value, {
    required this.isKeyNullAware,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    key.preVisit(visitor);
    value.preVisit(visitor);
  }

  @override
  String toString() => '${isKeyNullAware ? '?' : ''}$key: $value';

  @override
  void visit(Harness h, CollectionElementContext context) {
    SharedTypeSchemaView keySchema;
    SharedTypeSchemaView valueSchema;
    switch (context) {
      case CollectionElementContextMapEntry(:var keyType, :var valueType):
        keySchema = SharedTypeSchemaView(keyType);
        valueSchema = SharedTypeSchemaView(valueType);
      default:
        keySchema = valueSchema = h.operations.unknownType;
    }
    var keyType = h.typeAnalyzer.analyzeExpression(key, keySchema);
    h.flow.nullAwareMapEntry_valueBegin(
      key,
      keyType,
      isKeyNullAware: isKeyNullAware,
    );
    h.typeAnalyzer.analyzeExpression(value, valueSchema);
    h.flow.nullAwareMapEntry_end(isKeyNullAware: isKeyNullAware);
    h.irBuilder.apply(
      'mapEntry',
      [Kind.expression, Kind.expression],
      Kind.collectionElement,
      location: location,
    );
  }
}

/// Representation of a list literal in the pseudo-Dart language used for flow
/// analysis testing.
class MapLiteral extends Expression {
  final List<CollectionElement> elements;
  final Type keyType;
  final Type valueType;

  MapLiteral._(
    this.elements,
    this.keyType,
    this.valueType, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    for (var element in elements) {
      element.preVisit(visitor);
    }
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var context = CollectionElementContextMapEntry._(keyType, valueType);
    for (var element in elements) {
      h.typeAnalyzer.dispatchCollectionElement(element, context);
    }
    h.irBuilder.apply(
      'map',
      [for (var _ in elements) Kind.collectionElement],
      Kind.expression,
      location: location,
    );
    return ExpressionTypeAnalysisResult(
      type: h.operations.mapType(
        keyType: SharedTypeView(keyType),
        valueType: SharedTypeView(valueType),
      ),
    );
  }
}

class MapPattern extends Pattern {
  final ({Type keyType, Type valueType})? typeArguments;

  final List<MapPatternElement> elements;

  MapPattern._(this.typeArguments, this.elements, {required super.location})
    : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeMapPatternSchema(
        typeArguments: typeArguments?.wrapSharedTypeMapEntryView(),
        elements: elements,
      );

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    for (var element in elements) {
      element.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
    }
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var mapPatternResult = h.typeAnalyzer.analyzeMapPattern(
      context,
      this,
      typeArguments: typeArguments?.wrapSharedTypeMapEntryView(),
      elements: elements,
    );
    var matchedType = mapPatternResult.matchedValueType.unwrapTypeView<Type>();
    var requiredType = mapPatternResult.requiredType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.atom(requiredType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'mapPattern',
      [
        ...List.filled(elements.length, Kind.mapPatternElement),
        Kind.type,
        Kind.type,
      ],
      Kind.pattern,
      names: ['matchedType', 'requiredType'],
      location: location,
    );
    return mapPatternResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    var elements = [
      for (var element in this.elements)
        element._debugString(needsKeywordOrType: needsKeywordOrType),
    ];
    return '[${elements.join(', ')}]';
  }
}

abstract class MapPatternElement implements ListOrMapPatternElement {}

class MapPatternEntry extends Node implements MapPatternElement {
  final Expression key;
  final Pattern value;

  MapPatternEntry._(this.key, this.value, {required super.location})
    : super._();

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    value.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    return '$key: $value';
  }
}

class MiniAstOperations
    with TypeAnalyzerOperationsMixin<Var, Type, String>
    implements TypeAnalyzerOperations<Var, Type, String> {
  static const Map<String, bool> _coreExhaustiveness = const {
    '()': true,
    '(int, int?)': false,
    'bool': true,
    'dynamic': false,
    'int': false,
    'int?': false,
    'List<int>': false,
    'Never': false,
    'num': false,
    'num?': false,
    'Object': false,
    'Object?': false,
    'String': false,
    'String?': false,
  };

  static final Map<String, Type> _coreGlbs = {
    '_, int': Type('int'),
    '(int,), _': Type('(int,)'),
    '(num,), _': Type('(num,)'),
    'Object?, double': Type('double'),
    'Object?, int': Type('int'),
    'double, int': Type('Never'),
    'double?, int?': Type('Null'),
    'int?, num': Type('int'),
    'Null, int': Type('Never'),
  };

  static final Map<String, Type> _coreLubs = {
    'double, int': Type('num'),
    'double?, int?': Type('num?'),
    'int, num': Type('num'),
    'Null, bool': Type('bool?'),
    'Null, dynamic': Type('dynamic'),
    'Null, int': Type('int?'),
    'Null, Object': Type('Object?'),
    'Null, String': Type('String?'),
    'int, _': Type('int'),
    'List<_>, _': Type('List<_>'),
    'Null, _': Type('Null'),
  };

  static final Map<String, Type> _coreDownwardInferenceResults = {
    'bool <: bool': Type('bool'),
    'dynamic <: int': Type('dynamic'),
    'dynamic <: Null': Type('dynamic'),
    'error <: int': Type('error'),
    'error <: num': Type('error'),
    'int <: dynamic': Type('int'),
    'int <: int': Type('int'),
    'int <: Null': Type('int'),
    'int <: num': Type('int'),
    'int <: Object': Type('int'),
    'int <: Object?': Type('int'),
    'List <: Iterable<int>': Type('List<int>'),
    'Never <: int': Type('Never'),
    'Null <: int': Type('Null'),
    'Null <: Null': Type('Null'),
    'num <: int': Type('num'),
    'num <: Object': Type('num'),
    'Object <: num': Type('Object'),
    'String <: num': Type('String'),
  };

  static final Map<String, Type> _coreNormalizeResults = {
    'Object': Type('Object'),
    'FutureOr<Object>': Type('Object'),
    'double': Type('double'),
    'int': Type('int'),
    'int?': Type('int?'),
    'num': Type('num'),
    'String?': Type('String?'),
    'List<int>': Type('List<int>'),
  };

  @override
  late final SharedTypeView objectQuestionType = SharedTypeView(
    Type('Object?'),
  );

  @override
  late final SharedTypeView objectType = SharedTypeView(Type('Object'));

  @override
  late final SharedTypeSchemaView unknownType = SharedTypeSchemaView(Type('_'));

  @override
  late final SharedTypeView intType = SharedTypeView(Type('int'));

  @override
  late final SharedTypeView doubleType = SharedTypeView(Type('double'));

  final Map<String, bool> _exhaustiveness = Map.of(_coreExhaustiveness);

  final Map<String, Type> _extensionTypeErasure = {};

  final Map<String, Type> _glbs = Map.of(_coreGlbs);

  final Map<String, Type> _lubs = Map.of(_coreLubs);

  final Map<String, Type> _downwardInferenceResults = Map.of(
    _coreDownwardInferenceResults,
  );

  Map<String, Map<String, String>> _promotionExceptions = {};

  Map<String, Type> _normalizeResults = Map.of(_coreNormalizeResults);

  final TypeSystem _typeSystem = TypeSystem();

  final _variance = <String, List<Variance>>{};

  @override
  final SharedTypeView boolType = SharedTypeView(Type('bool'));

  @override
  SharedTypeView get dynamicType => SharedTypeView(DynamicType.instance);

  @override
  SharedTypeView get errorType => SharedTypeView(InvalidType.instance);

  @override
  SharedTypeView get neverType => SharedTypeView(NeverType.instance);

  @override
  SharedTypeView get nullType => SharedTypeView(NullType.instance);

  /// Updates the harness with a new result for [downwardInfer].
  void addDownwardInfer({
    required String name,
    required String context,
    required String result,
  }) {
    var query = '$name <: $context';
    _downwardInferenceResults[query] = Type(result);
  }

  /// Updates the harness so that when an [isAlwaysExhaustiveType] query is
  /// invoked on type [type], [isExhaustive] will be returned.
  void addExhaustiveness(String type, bool isExhaustive) {
    _exhaustiveness[type] = isExhaustive;
  }

  /// Updates the harness so that when an extension type erasure query is
  /// invoked on type [type], [representation] will be returned.
  void addExtensionTypeErasure(String type, String representation) {
    _extensionTypeErasure[type] = Type(representation);
  }

  void addLub(String type1, String type2, String resultType) {
    _lubs['$type1, $type2'] = Type(resultType);
  }

  void addPromotionException(String from, String to, String result) {
    (_promotionExceptions[from] ??= {})[to] = result;
  }

  void addSuperInterfaces(
    String className,
    List<Type> Function(List<Type>) template,
  ) {
    _typeSystem.addSuperInterfaces(className, template);
  }

  void addVariance(String typeName, List<Variance> varianceByArgument) {
    _variance[typeName] = varianceByArgument;
  }

  @override
  TypeClassification classifyType(SharedTypeView type) {
    if (isSubtypeOfInternal(type.unwrapTypeView<Type>(), Type('Object'))) {
      return TypeClassification.nonNullable;
    } else if (isSubtypeOfInternal(
      type.unwrapTypeView<Type>(),
      NullType.instance,
    )) {
      return TypeClassification.nullOrEquivalent;
    } else {
      return TypeClassification.potentiallyNullable;
    }
  }

  @override
  TypeConstraintGenerator<Var, Type, String, Node>
  createTypeConstraintGenerator({
    required TypeConstraintGenerationDataForTesting?
    typeConstraintGenerationDataForTesting,
    required List<SharedTypeParameterView> typeParametersToInfer,
    required TypeAnalyzerOperations<Var, Type, String> typeAnalyzerOperations,
    required bool inferenceUsingBoundsIsEnabled,
  }) {
    return TypeConstraintGatherer({
      for (var typeParameter in typeParametersToInfer)
        typeParameter
            .unwrapTypeParameterViewAsTypeParameterStructure<TypeParameter>()
            .name,
    });
  }

  /// Returns the downward inference result of a type with the given [name],
  /// in the [context]. For example infer `List<int>` from `Iterable<int>`.
  Type downwardInfer(String name, Type context) {
    var query = '$name <: $context';
    return _downwardInferenceResults[query] ??
        fail('Unknown downward inference query: $query');
  }

  @override
  SharedTypeView extensionTypeErasure(SharedTypeView type) {
    var query = '${type.unwrapTypeView()}';
    return SharedTypeView(
      _extensionTypeErasure[query] ?? type.unwrapTypeView(),
    );
  }

  @override
  SharedTypeView factor(SharedTypeView from, SharedTypeView what) {
    return SharedTypeView(
      _typeSystem.factor(
        from.unwrapTypeView<Type>(),
        what.unwrapTypeView<Type>(),
      ),
    );
  }

  @override
  Type futureTypeInternal(Type argumentType) {
    return PrimaryType(TypeRegistry.future, args: [argumentType]);
  }

  @override
  TypeDeclarationKind? getTypeDeclarationKindInternal(Type type) {
    if (isInterfaceTypeInternal(type)) {
      return TypeDeclarationKind.interfaceDeclaration;
    } else if (isExtensionTypeInternal(type)) {
      return TypeDeclarationKind.extensionTypeDeclaration;
    } else {
      return null;
    }
  }

  @override
  Variance getTypeParameterVariance(
    String typeDeclaration,
    int parameterIndex,
  ) {
    return _variance[typeDeclaration]?[parameterIndex] ?? Variance.covariant;
  }

  @override
  Type glbInternal(Type type1, Type type2) {
    if (type1.type == type2.type) return type1;
    var typeNames = [type1.type, type2.type];
    typeNames.sort();
    var query = typeNames.join(', ');
    return _glbs[query] ?? fail('Unknown glb query: $query');
  }

  @override
  SharedTypeView greatestClosure(SharedTypeSchemaView schema) {
    return SharedTypeView(
      schema.unwrapTypeSchemaView<Type>().closureWithRespectToUnknown(
            covariant: true,
          ) ??
          schema.unwrapTypeSchemaView(),
    );
  }

  @override
  Type greatestClosureOfTypeInternal(
    Type type,
    List<SharedTypeParameter> typeParametersToEliminate,
  ) {
    // TODO(paulberry): Implement greatest closure of types in mini ast.
    throw UnimplementedError();
  }

  @override
  bool isAlwaysExhaustiveType(SharedTypeView type) {
    var query = type.unwrapTypeView<Type>().type;
    return _exhaustiveness[query] ??
        fail('Unknown exhaustiveness query: $query');
  }

  @override
  bool isAssignableTo(SharedTypeView fromType, SharedTypeView toType) {
    if (fromType is DynamicType) return true;
    if (fromType is InvalidType) return true;
    return isSubtypeOfInternal(
      fromType.unwrapTypeView<Type>(),
      toType.unwrapTypeView<Type>(),
    );
  }

  @override
  bool isBottomType(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    return unwrappedType is NeverType && !unwrappedType.isQuestionType;
  }

  @override
  bool isDartCoreFunctionInternal(Type type) {
    return type is PrimaryType &&
        !type.isQuestionType &&
        type.name == 'Function' &&
        type.args.isEmpty;
  }

  @override
  bool isDartCoreRecordInternal(Type type) {
    return type is PrimaryType &&
        !type.isQuestionType &&
        type.name == 'Record' &&
        type.args.isEmpty;
  }

  @override
  bool isExtensionTypeInternal(Type type) {
    // TODO(cstefantsova): Add the support for extension types in the mini ast
    // testing framework.
    return false;
  }

  @override
  bool isFinal(Var variable) {
    return variable.isFinal;
  }

  @override
  bool isInterfaceTypeInternal(Type type) {
    return type is PrimaryType && type.isInterfaceType;
  }

  @override
  bool isKnownType(SharedTypeSchemaView typeSchema) {
    var unwrapped = typeSchema.unwrapTypeSchemaView<Type>();
    switch (unwrapped) {
      case FutureOrType(:var typeArgument):
        return isKnownType(SharedTypeSchemaView(typeArgument));
      case PrimaryType(:var args):
        for (var arg in args) {
          if (!isKnownType(SharedTypeSchemaView(arg))) {
            return false;
          }
        }
        return true;
      case FunctionType(
        :var returnType,
        :var typeParametersShared,
        :var positionalParameters,
        :var namedParameters,
      ):
        if (!isKnownType(SharedTypeSchemaView(returnType))) {
          return false;
        }
        for (var typeParameter in typeParametersShared) {
          if (!isKnownType(SharedTypeSchemaView(typeParameter.bound))) {
            return false;
          }
        }
        for (var positionalParameter in positionalParameters) {
          if (!isKnownType(SharedTypeSchemaView(positionalParameter))) {
            return false;
          }
        }
        for (var namedParameter in namedParameters) {
          if (!isKnownType(SharedTypeSchemaView(namedParameter.type))) {
            return false;
          }
        }
        return true;
      case RecordType(:var positionalTypes, :var namedTypes):
        for (var positionalType in positionalTypes) {
          if (!isKnownType(SharedTypeSchemaView(positionalType))) {
            return false;
          }
        }
        for (var namedType in namedTypes) {
          if (!isKnownType(SharedTypeSchemaView(namedType.type))) {
            return false;
          }
        }
        return true;
      case UnknownType():
        return false;
      default:
        return true;
    }
  }

  @override
  bool isNonNullableInternal(Type type) {
    Type unwrappedType = type;
    if (unwrappedType is DynamicType ||
        unwrappedType is SharedUnknownType ||
        unwrappedType is VoidType ||
        unwrappedType is NullType ||
        unwrappedType is InvalidType) {
      return false;
    } else if (unwrappedType case TypeParameterType(
      :var promotion,
      :var typeParameter,
      isQuestionType: false,
    )) {
      if (promotion != null) {
        return isNonNullableInternal(promotion);
      } else {
        return isNonNullableInternal(typeParameter.bound);
      }
    } else if (type.isQuestionType) {
      return false;
    } else if (matchFutureOrInternal(unwrappedType) case Type typeArgument?) {
      return isNonNullableInternal(typeArgument);
    }
    return true;
  }

  @override
  bool isNullableInternal(Type type) {
    Type unwrappedType = type;
    if (unwrappedType is DynamicType ||
        unwrappedType is SharedUnknownType ||
        unwrappedType is VoidType ||
        unwrappedType is NullType) {
      return true;
    } else if (type.isQuestionType) {
      return false;
    } else if (matchFutureOrInternal(unwrappedType) case Type typeArgument?) {
      return isNullableInternal(typeArgument);
    }
    // TODO(cstefantsova): Update to a fast-pass implementation when the
    // mini-ast testing framework supports looking up superinterfaces of
    // extension types or looking up bounds of type parameters.
    return _typeSystem.isSubtype(NullType.instance, unwrappedType);
  }

  @override
  bool isObject(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    return unwrappedType is PrimaryType &&
        !unwrappedType.isQuestionType &&
        unwrappedType.name == 'Object' &&
        unwrappedType.args.isEmpty;
  }

  @override
  bool isPropertyPromotable(covariant _PropertyElement property) =>
      property.isPromotable;

  @override
  bool isSubtypeOfInternal(Type leftType, Type rightType) {
    return _typeSystem.isSubtype(leftType, rightType);
  }

  @override
  bool isTypeParameterType(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    return unwrappedType is TypeParameterType && !unwrappedType.isQuestionType;
  }

  @override
  bool isTypeSchemaSatisfied({
    required SharedTypeSchemaView typeSchema,
    required SharedTypeView type,
  }) {
    return isSubtypeOfInternal(
      type.unwrapTypeView<Type>(),
      typeSchema.unwrapTypeSchemaView<Type>(),
    );
  }

  @override
  bool isVariableFinal(Var node) {
    return node.isFinal;
  }

  @override
  SharedTypeSchemaView iterableTypeSchema(
    SharedTypeSchemaView elementTypeSchema,
  ) {
    return SharedTypeSchemaView(
      PrimaryType(
        TypeRegistry.iterable,
        args: [elementTypeSchema.unwrapTypeSchemaView<Type>()],
      ),
    );
  }

  @override
  Type leastClosureOfTypeInternal(
    Type type,
    List<SharedTypeParameter> typeParametersToEliminate,
  ) {
    // TODO(paulberry): Implement greatest closure of types in mini ast.
    throw UnimplementedError();
  }

  @override
  Type listTypeInternal(Type elementType) {
    return PrimaryType(TypeRegistry.list, args: [elementType]);
  }

  @override
  Type lubInternal(Type type1, Type type2) {
    if (type1 == type2) {
      return type1;
    } else if (promoteToNonNull(SharedTypeView(type1)) ==
        SharedTypeView(type2)) {
      return type1;
    } else if (promoteToNonNull(SharedTypeView(type2)) ==
        SharedTypeView(type1)) {
      return type2;
    } else if (type1 is NullType &&
        promoteToNonNull(SharedTypeView(type2)) != SharedTypeView(type2)) {
      // type2 is already nullable
      return type2;
    } else if (type2 is NullType &&
        promoteToNonNull(SharedTypeView(type1)) != SharedTypeView(type1)) {
      // type1 is already nullable
      return type1;
    } else if (type1 is NeverType && !type1.isQuestionType) {
      return type2;
    } else if (type2 is NeverType && !type2.isQuestionType) {
      return type1;
    } else {
      var typeNames = [type1.type, type2.type];
      typeNames.sort();
      var query = typeNames.join(', ');
      return _lubs[query] ?? fail('Unknown lub query: $query');
    }
  }

  @override
  Type makeNullableInternal(Type type) => lubInternal(type, NullType.instance);

  @override
  Type mapTypeInternal({required Type keyType, required Type valueType}) {
    return PrimaryType(TypeRegistry.map, args: [keyType, valueType]);
  }

  @override
  Type? matchFutureOrInternal(Type type) {
    if (type is FutureOrType) {
      return type.typeArgument;
    }
    return null;
  }

  @override
  TypeParameter? matchInferableParameterInternal(Type type) {
    if (type case TypeParameterType(
      :var typeParameter,
      isQuestionType: false,
    )) {
      return typeParameter;
    } else {
      return null;
    }
  }

  @override
  Type? matchIterableTypeInternal(Type type) {
    if (type is PrimaryType && !type.isQuestionType && type.args.length == 1) {
      if (type.name == 'Iterable' || type.name == 'List') {
        return type.args[0];
      }
    }
    return null;
  }

  @override
  SharedTypeView? matchListType(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    if (unwrappedType is PrimaryType &&
        !unwrappedType.isQuestionType &&
        unwrappedType.name == 'List' &&
        unwrappedType.args.length == 1) {
      return SharedTypeView(unwrappedType.args[0]);
    }
    return null;
  }

  @override
  ({SharedTypeView keyType, SharedTypeView valueType})? matchMapType(
    SharedTypeView type,
  ) {
    Type unwrappedType = type.unwrapTypeView();
    if (unwrappedType is PrimaryType &&
        !unwrappedType.isQuestionType &&
        unwrappedType.name == 'Map' &&
        unwrappedType.args.length == 2) {
      return (
        keyType: SharedTypeView(unwrappedType.args[0]),
        valueType: SharedTypeView(unwrappedType.args[1]),
      );
    }
    return null;
  }

  @override
  SharedTypeView? matchStreamType(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    if (unwrappedType is PrimaryType &&
        !unwrappedType.isQuestionType &&
        unwrappedType.args.length == 1) {
      if (unwrappedType.name == 'Stream') {
        return SharedTypeView(unwrappedType.args[0]);
      }
    }
    return null;
  }

  @override
  TypeDeclarationMatchResult<Type, String>? matchTypeDeclarationTypeInternal(
    Type type,
  ) {
    if (type is! PrimaryType) return null;
    TypeDeclarationKind typeDeclarationKind;
    if (type.isInterfaceType) {
      typeDeclarationKind = TypeDeclarationKind.interfaceDeclaration;
    } else if (isExtensionTypeInternal(type)) {
      typeDeclarationKind = TypeDeclarationKind.extensionTypeDeclaration;
    } else {
      return null;
    }
    return new TypeDeclarationMatchResult(
      typeDeclarationKind: typeDeclarationKind,
      typeDeclaration: type.name,
      typeDeclarationType: type,
      typeArguments: type.args,
    );
  }

  @override
  Type? matchTypeParameterBoundInternal(Type type) {
    if (type case TypeParameterType(
      :var promotion,
      :var typeParameter,
      isQuestionType: false,
    )) {
      return promotion ?? typeParameter.bound;
    } else {
      return null;
    }
  }

  @override
  SharedTypeView normalize(SharedTypeView type) {
    var query = '${type.unwrapTypeView()}';
    return SharedTypeView(
      _normalizeResults[query] ?? fail('Unknown query: $query'),
    );
  }

  @override
  SharedTypeView promoteToNonNull(SharedTypeView type) {
    Type unwrappedType = type.unwrapTypeView();
    if (unwrappedType.isQuestionType) {
      return SharedTypeView(unwrappedType.asQuestionType(false));
    } else if (unwrappedType is NullType) {
      return SharedTypeView(NeverType.instance);
    } else {
      return type;
    }
  }

  @override
  RecordType recordTypeInternal({
    required List<SharedType> positional,
    required covariant List<(String, SharedType)> named,
  }) {
    return RecordType(
      positionalTypes: positional.cast<Type>(),
      namedTypes: [
        for (var (name, type) in named)
          NamedType(name: name, type: type as Type),
      ]..sort((a, b) => a.name.compareTo(b.name)),
    );
  }

  @override
  SharedTypeSchemaView streamTypeSchema(
    SharedTypeSchemaView elementTypeSchema,
  ) {
    return SharedTypeSchemaView(
      PrimaryType(
        TypeRegistry.stream,
        args: [elementTypeSchema.unwrapTypeSchemaView<Type>()],
      ),
    );
  }

  @override
  SharedTypeView? tryPromoteToType(SharedTypeView to, SharedTypeView from) {
    var exception =
        (_promotionExceptions[from.unwrapTypeView<Type>().type] ?? {})[to
            .unwrapTypeView<Type>()
            .type];
    if (exception != null) {
      return SharedTypeView(Type(exception));
    }
    if (isSubtypeOfInternal(
      to.unwrapTypeView<Type>(),
      from.unwrapTypeView<Type>(),
    )) {
      return to;
    } else {
      return null;
    }
  }

  @override
  SharedTypeSchemaView typeToSchema(SharedTypeView type) =>
      SharedTypeSchemaView(type.unwrapTypeView());

  @override
  SharedTypeView variableType(Var variable) {
    return SharedTypeView(variable.type);
  }

  @override
  PropertyNonPromotabilityReason? whyPropertyIsNotPromotable(
    covariant _PropertyElement property,
  ) => property.whyNotPromotable;
}

/// Representation of an expression or statement in the pseudo-Dart language
/// used for flow analysis testing.
class Node {
  static int _nextId = 0;

  /// Tracks all [Node] object that have had an [errorId] assigned, but haven't
  /// had [errorId] queried.  This is used to detect unused error IDs so that we
  /// can keep the test cases clean.
  static final Set<Node> _nodesWithUnusedErrorIds = {};

  final int id;

  final String location;

  String? _errorId;

  factory Node.placeholder() => Node._(location: computeLocation());

  Node._({required this.location}) : id = _nextId++;

  String get errorId {
    _nodesWithUnusedErrorIds.remove(this);
    String? errorId = _errorId;
    if (errorId == null) {
      fail('No error ID assigned for $runtimeType $this at $location');
    } else {
      return errorId;
    }
  }

  set errorId(String value) {
    _errorId = value;
    _nodesWithUnusedErrorIds.add(this);
  }

  @override
  String toString() => 'Node#$id';
}

class NonNullAssert extends Expression {
  final Expression operand;

  NonNullAssert._(this.operand, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    operand.preVisit(visitor);
  }

  @override
  String toString() => '$operand!';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeNonNullAssert(this, operand);
  }
}

class Not extends Expression {
  final Expression operand;

  Not._(this.operand, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    operand.preVisit(visitor);
  }

  @override
  String toString() => '!$operand';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeLogicalNot(this, operand);
  }
}

class NullCheckOrAssertPattern extends Pattern {
  final Pattern inner;

  final bool isAssert;

  NullCheckOrAssertPattern._(
    this.inner,
    this.isAssert, {
    required super.location,
  }) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) => h.typeAnalyzer
      .analyzeNullCheckOrAssertPatternSchema(inner, isAssert: isAssert);

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    inner.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeNullCheckOrAssertPattern(
      context,
      this,
      inner,
      isAssert: isAssert,
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      isAssert ? 'nullAssertPattern' : 'nullCheckPattern',
      [Kind.pattern, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) =>
      '${inner._debugString(needsKeywordOrType: needsKeywordOrType)}?';
}

class NullLiteral extends ConstExpression {
  NullLiteral._({required super.location}) : super._();

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'null';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeNullLiteral(this);
    h.irBuilder.atom('null', Kind.expression, location: location);
    return result;
  }
}

class ObjectPattern extends Pattern {
  final PrimaryType requiredType;
  final List<RecordPatternField> fields;

  ObjectPattern._({
    required this.requiredType,
    required this.fields,
    required super.location,
  }) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) {
    return h.typeAnalyzer.analyzeObjectPatternSchema(
      SharedTypeView(requiredType),
    );
  }

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    for (var field in fields) {
      field.pattern.preVisit(
        visitor,
        variableBinder,
        isInAssignment: isInAssignment,
      );
    }
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var objectPatternResult = h.typeAnalyzer.analyzeObjectPattern(
      context,
      this,
      fields: fields,
    );
    var matchedType =
        objectPatternResult.matchedValueType.unwrapTypeView<Type>();
    var requiredType = objectPatternResult.requiredType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.atom(requiredType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'objectPattern',
      [...List.filled(fields.length, Kind.pattern), Kind.type, Kind.type],
      Kind.pattern,
      names: ['matchedType', 'requiredType'],
      location: location,
    );
    return objectPatternResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    var fieldStrings = [
      for (var field in fields)
        field.pattern._debugString(needsKeywordOrType: needsKeywordOrType),
    ];
    final requiredType = this.requiredType;
    return '$requiredType(${fieldStrings.join(', ')})';
  }
}

class ParenthesizedExpression extends Expression {
  final Expression expr;

  ParenthesizedExpression._(this.expr, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    expr.preVisit(visitor);
  }

  @override
  String toString() => '($expr)';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeParenthesizedExpression(this, expr, schema);
  }
}

class ParenthesizedPattern extends Pattern {
  final Pattern inner;

  ParenthesizedPattern._(this.inner, {required super.location}) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) => inner.computeSchema(h);

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) => inner.preVisit(visitor, variableBinder, isInAssignment: isInAssignment);

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    return inner.visit(h, context);
  }

  @override
  String _debugString({required bool needsKeywordOrType}) =>
      '(${inner._debugString(needsKeywordOrType: false)})';
}

abstract class Pattern extends Node
    with PossiblyGuardedPattern
    implements ListPatternElement {
  Pattern._({required super.location}) : super._();

  Pattern get nullAssert =>
      NullCheckOrAssertPattern._(this, true, location: computeLocation());

  Pattern get nullCheck =>
      NullCheckOrAssertPattern._(this, false, location: computeLocation());

  Pattern get parenthesized =>
      ParenthesizedPattern._(this, location: computeLocation());

  @override
  GuardedPattern get _asGuardedPattern {
    return GuardedPattern._(pattern: this, guard: null, location: location);
  }

  Pattern and(Pattern other) =>
      LogicalAndPattern._(this, other, location: computeLocation());

  Pattern as_(String type) =>
      new CastPattern(this, Type(type), location: computeLocation());

  /// Creates a pattern assignment expression assigning [rhs] to this pattern.
  Expression assign(ProtoExpression rhs) {
    var location = computeLocation();
    return PatternAssignment._(
      this,
      rhs.asExpression(location: location),
      location: location,
    );
  }

  SharedTypeSchemaView computeSchema(Harness h);

  Pattern or(Pattern other) =>
      LogicalOrPattern(this, other, location: computeLocation());

  RecordPatternField recordField([String? name]) {
    return RecordPatternField(
      name: name,
      pattern: this,
      location: computeLocation(),
    );
  }

  @override
  String toString() => _debugString(needsKeywordOrType: true);

  PatternResult visit(Harness h, SharedMatchContext context);

  GuardedPattern when(ProtoExpression? guard) {
    return GuardedPattern._(
      pattern: this,
      guard: guard?.asExpression(location: location),
      location: location,
    );
  }
}

class PatternAssignment extends Expression {
  final Pattern lhs;
  final Expression rhs;

  PatternAssignment._(this.lhs, this.rhs, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    lhs.preVisit(visitor, variableBinder, isInAssignment: true);
    variableBinder.casePatternFinish();
    variableBinder.finish();
    rhs.preVisit(visitor);
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzePatternAssignment(this, lhs, rhs);
    h.irBuilder.apply(
      'patternAssignment',
      [Kind.expression, Kind.pattern],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

class PatternForIn extends Statement {
  final bool hasAwait;
  final Pattern pattern;
  final Expression expression;
  final Statement body;

  PatternForIn(
    this.pattern,
    this.expression,
    this.body, {
    required this.hasAwait,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    expression.preVisit(visitor);

    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    pattern.preVisit(visitor, variableBinder, isInAssignment: false);
    variableBinder.casePatternFinish();
    variableBinder.finish();

    visitor._assignedVariables.beginNode();
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() {
    return 'for ($pattern in $expression) $body';
  }

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzePatternForIn(
      node: this,
      hasAwait: hasAwait,
      pattern: pattern,
      expression: expression,
      dispatchBody: () {
        h.typeAnalyzer.dispatchStatement(body);
      },
    );
    h.irBuilder.apply(
      'forEach',
      [Kind.expression, Kind.pattern, Kind.statement],
      Kind.statement,
      location: location,
    );
  }
}

class PatternForInElement extends CollectionElement {
  final bool hasAwait;
  final Pattern pattern;
  final Expression expression;
  final CollectionElement body;

  PatternForInElement(
    this.pattern,
    this.expression,
    this.body, {
    required this.hasAwait,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    expression.preVisit(visitor);

    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    pattern.preVisit(visitor, variableBinder, isInAssignment: false);
    variableBinder.casePatternFinish();
    variableBinder.finish();

    visitor._assignedVariables.beginNode();
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  void visit(Harness h, covariant CollectionElementContext context) {
    h.typeAnalyzer.analyzePatternForIn(
      node: this,
      hasAwait: hasAwait,
      pattern: pattern,
      expression: expression,
      dispatchBody: () {
        h.typeAnalyzer.dispatchCollectionElement(body, context);
      },
    );
    h.irBuilder.apply(
      'forEach',
      [Kind.expression, Kind.pattern, Kind.collectionElement],
      Kind.collectionElement,
      location: location,
    );
  }
}

class PatternVariableDeclaration extends Statement {
  final bool isFinal;
  final Pattern pattern;
  final Expression initializer;

  PatternVariableDeclaration._(
    this.pattern,
    this.initializer, {
    required this.isFinal,
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    var variableBinder = _VariableBinder(visitor);
    variableBinder.casePatternStart();
    pattern.preVisit(visitor, variableBinder, isInAssignment: false);
    variableBinder.casePatternFinish();
    variableBinder.finish();
    initializer.preVisit(visitor);
  }

  @override
  String toString() {
    var parts = <String>[
      if (isFinal) 'final',
      pattern._debugString(needsKeywordOrType: !isFinal),
      '= $initializer',
    ];
    return '${parts.join(' ')};';
  }

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzePatternVariableDeclaration(
      this,
      pattern,
      initializer,
      isFinal: isFinal,
    );
    h.irBuilder.apply(
      ['match', if (isFinal) 'final'].join('_'),
      [Kind.expression, Kind.pattern],
      Kind.statement,
      location: location,
    );
  }
}

/// A variable modelling an implicit join of variables declared inside
/// logical-or patterns or switch cases sharing a body.
///
/// The analyzer and CFE make such variables automatically when needed, but in
/// the flow analysis and type inference unit tests, we create them manually so
/// that we can refer to them in later code.
class PatternVariableJoin extends Var {
  /// The component variables joined together by this variable.  When the test
  /// is run, an assertion will verify that these components match those passed
  /// to [VariableBinder.joinPatternVariables].
  final List<Var> expectedComponents;

  /// Indicates whether this variable has been found to be inconsistent; a value
  /// of `true` either means that the variable is consistent or that analysis
  /// has not yet completed.
  @override
  JoinedPatternVariableInconsistency inconsistency =
      JoinedPatternVariableInconsistency.none;

  /// Indicates whether [VariableBinder.joinPatternVariables] has been called
  /// for this variable join yet.
  bool isJoined = false;

  PatternVariableJoin(
    super.name, {
    required this.expectedComponents,
    super.identity,
  }) : super(location: computeLocation()) {
    for (var component in expectedComponents) {
      assert(component._joinedVar == null);
      component._joinedVar = this;
    }
  }

  @override
  String get stringToCheckVariables {
    return toString();
  }

  @override
  String toString() {
    var declarationStr = <String>[
      if (_type != null) ...[
        if (inconsistency != JoinedPatternVariableInconsistency.none)
          'notConsistent:${inconsistency.name}',
        if (isFinal) 'final',
        type.type,
      ],
      name,
    ].join(' ');
    var componentsStr = expectedComponents
        .map((v) => v.stringToCheckVariables)
        .join(', ');
    return '$declarationStr = [$componentsStr]';
  }

  /// Called by [VariableBinder.joinPatternVariables].
  void _handleJoin({
    required List<Var> components,
    required JoinedPatternVariableInconsistency inconsistency,
    required PreVisitor visitor,
  }) {
    expect(isJoined, false);
    expect(
      components.map((c) => c.identity),
      expectedComponents.map((c) => c.identity),
      reason: 'at $location',
    );
    expect(components, expectedComponents, reason: 'at $location');
    this.inconsistency = inconsistency;
    this.isJoined = true;
    visitor._assignedVariables.declare(this);
  }
}

class PlaceholderExpression extends ConstExpression {
  final Type type;

  PlaceholderExpression._(this.type, {required super.location}) : super._();

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => '(expr with type $type)';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    h.irBuilder.atom(type.type, Kind.type, location: location);
    h.irBuilder.apply('expr', [Kind.type], Kind.expression, location: location);
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }
}

/// Mixin containing logic shared by [Pattern] and [GuardedPattern].  Both of
/// these types can be used in a case where a pattern with an optional guard is
/// expected.
mixin PossiblyGuardedPattern on Node implements ProtoSwitchHead {
  @override
  SwitchHead get asSwitchHead =>
      SwitchHeadCase._(_asGuardedPattern, location: location);

  /// Converts `this` to a [GuardedPattern], including a `null` guard if
  /// necessary.
  GuardedPattern get _asGuardedPattern;

  SwitchStatementMember then(List<ProtoStatement> body) {
    return SwitchStatementMember._(
      [SwitchHeadCase._(_asGuardedPattern, location: location)],
      Block._(body, location: location),
      hasLabels: false,
      location: location,
    );
  }

  ExpressionCase thenExpr(ProtoExpression body) {
    var location = computeLocation();
    return ExpressionCase._(
      _asGuardedPattern,
      body.asExpression(location: location),
      location: location,
    );
  }
}

/// Representation of a postfix increment or decrement operation.
class PostIncDec extends Expression {
  final LValue lhs;

  PostIncDec(this.lhs, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    lhs.preVisit(visitor, disposition: _LValueDisposition.readWrite);
  }

  @override
  String toString() => '$lhs++';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    Type type =
        h.typeAnalyzer
            .analyzeExpression(lhs, h.operations.unknownType)
            .unwrapTypeView();
    lhs._visitPostIncDec(h, this, type);
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }
}

/// Data structure holding information needed during the "pre-visit" phase of
/// type analysis.
class PreVisitor {
  final AssignedVariables<Node, Var> _assignedVariables =
      AssignedVariables<Node, Var>();

  final VariableBinderErrors<Node, Var>? errors;

  PreVisitor(this.errors);
}

/// Base class for language constructs that, at a given point in flow analysis,
/// might or might not be promoted.
abstract class Promotable {
  /// Makes the appropriate calls to [AssignedVariables] and [VariableBinder]
  /// for this syntactic construct.
  void preVisit(PreVisitor visitor);

  /// Queries the current promotion status of `this`.  Return value is either a
  /// type (if `this` is promoted), or `null` (if it isn't).
  Type? _getPromotedType(Harness h);
}

/// Base class for l-values that, at a given point in flow analysis, might or
/// might not be promoted.
abstract class PromotableLValue extends LValue implements Promotable {
  PromotableLValue._({required super.location}) : super._();
}

class Property extends PromotableLValue {
  final Expression target;

  final String propertyName;

  final bool isNullAware;

  Property._(
    this.target,
    this.propertyName, {
    required super.location,
    required this.isNullAware,
  }) : super._();

  @override
  void preVisit(
    PreVisitor visitor, {
    _LValueDisposition disposition = _LValueDisposition.read,
  }) {
    target.preVisit(visitor);
  }

  @override
  String toString() {
    var q = isNullAware ? '?' : '';
    return '$target$q.$propertyName';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzePropertyGet(
      this,
      target is CascadePlaceholder ? null : target,
      propertyName,
      isNullAware: isNullAware,
    );
  }

  @override
  Type? _getPromotedType(Harness h) {
    if (isNullAware) {
      fail(
        "at $location: it doesn't make sense to compute the promoted type of "
        'a null-aware property.',
      );
    }
    var receiverType =
        h.typeAnalyzer
            .analyzeExpression(target, h.operations.unknownType)
            .unwrapTypeView<Type>();
    var member = h.typeAnalyzer._lookupMember(receiverType, propertyName);
    return h.flow
        .promotedPropertyType(
          ExpressionPropertyTarget(target),
          propertyName,
          member,
          SharedTypeView(member!._type),
        )
        ?.unwrapTypeView();
  }

  @override
  void _visitPostIncDec(
    Harness h,
    Expression postIncDecExpression,
    Type writtenType,
  ) {
    assert(!isNullAware); // TODO(paulberry): implement null-aware support
    // No flow analysis impact
  }

  @override
  void _visitWrite(
    Harness h,
    Expression assignmentExpression,
    Type writtenType,
    Expression? rhs,
  ) {
    assert(!isNullAware); // TODO(paulberry): implement null-aware support
    // No flow analysis impact
  }
}

/// Common functionality shared by constructs that can be used where a
/// collection element is expected, in in the pseudo-Dart language used for flow
/// analysis testing.
///
/// The reason this mixin is distinct from the [CollectionElement] class is
/// because both [Expression]s and other [CollectionElement]s (`if` and `for`
/// elements) can be used where a collection element is expected (because an
/// expression inside a collection simply becomes an
/// [ExpressionCollectionElement]).
mixin ProtoCollectionElement<Self extends ProtoCollectionElement<dynamic>> {
  /// Converts `this` to a [CollectionElement]. If it's already a
  /// [CollectionElement], it is returned unchanged. If it's an [Expression],
  /// it's converted into a collection element.
  ///
  /// In general, tests shouldn't need to call this method directly; instead
  /// they should simply be able to use either an [Expression] or some other
  /// [CollectionElement] in a context where a [CollectionElement] is expected,
  /// and the test infrastructure will call this getter as needed.
  CollectionElement asCollectionElement({required String location});

  /// Wraps `this` in such a way that, when the test is run, it will verify that
  /// the IR produced matches [expectedIR].
  Self checkIR(String expectedIR);
}

/// Common functionality shared by constructs that can be used where an
/// expression is expected, in in the pseudo-Dart language used for flow
/// analysis testing.
///
/// The reason this mixin is distinct from the [Expression] class is because
/// both [Expression]s and [Var]s can be used where a statement is expected
/// (because a [Var] in an expression context simply becomes a read of the
/// variable).
mixin ProtoExpression
    implements ProtoStatement<Expression>, ProtoCollectionElement<Expression> {
  /// If `this` is an expression `x`, creates a dot shorthand wrapper around
  /// `x`.
  Expression get dotShorthand {
    var location = computeLocation();
    return new DotShorthand._(
      asExpression(location: location),
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x!`.
  Expression get nonNullAssert {
    var location = computeLocation();
    return new NonNullAssert._(
      asExpression(location: location),
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `!x`.
  Expression get not {
    var location = computeLocation();
    return new Not._(asExpression(location: location), location: location);
  }

  /// If `this` is an expression `x`, creates the expression `(x)`.
  Expression get parenthesized {
    var location = computeLocation();
    return new ParenthesizedExpression._(
      asExpression(location: location),
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x && other`.
  Expression and(ProtoExpression other) {
    var location = computeLocation();
    return new Logical._(
      asExpression(location: location),
      other.asExpression(location: location),
      isAnd: true,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x as typeStr`.
  Expression as_(String typeStr) {
    var location = computeLocation();
    return new As._(
      asExpression(location: location),
      Type(typeStr),
      location: location,
    );
  }

  @override
  CollectionElement asCollectionElement({required String location}) =>
      ExpressionCollectionElement(
        asExpression(location: location),
        location: location,
      );

  /// Converts `this` to an [Expression]. If it's already an [Expression], it is
  /// returned unchanged. If it's something else (e.g. a [Var]), it's converted
  /// into an [Expression].
  ///
  /// In general, tests shouldn't need to call this method directly; instead
  /// they should simply be able to use either anything implementing the
  /// [ProtoExpression] interface in a context where an [Expression] is
  /// expected, and the test infrastructure will call this getter as needed.
  Expression asExpression({required String location});

  @override
  Statement asStatement({required String location}) =>
      new ExpressionStatement._(
        asExpression(location: location),
        location: location,
      );

  /// If `this` is an expression `x`, creates a cascade expression with `x` as
  /// the target, and [sections] as the cascade sections. [isNullAware]
  /// indicates whether this is a null-aware cascade.
  ///
  /// Since each cascade section needs to implicitly refer to the target of the
  /// cascade, the caller should pass in a closure for each cascade section; the
  /// closures will be immediately invoked, passing in a [CascadePlaceholder]
  /// pseudo-expression representing the implicit reference to the cascade
  /// target.
  Expression cascade(
    List<ProtoExpression Function(CascadePlaceholder)> sections, {
    bool isNullAware = false,
  }) {
    var location = computeLocation();
    return Cascade._(
      asExpression(location: location),
      [
        for (var section in sections)
          section(
            CascadePlaceholder._(location: location),
          ).asExpression(location: location),
      ],
      isNullAware: isNullAware,
      location: location,
    );
  }

  /// Wraps `this` in such a way that, when the test is run, it will verify that
  /// the IR produced matches [expectedIR].
  @override
  Expression checkIR(String expectedIR) {
    var location = computeLocation();
    return asExpression(location: location).._expectedIR = expectedIR;
  }

  /// Wraps `this` in such a way that, when the test is run, it will verify that
  /// the context provided when analyzing the expression matches
  /// [expectedSchema].
  Expression checkSchema(String expectedSchema) {
    var location = computeLocation();
    return asExpression(location: location).._expectedSchema = expectedSchema;
  }

  /// Creates an [Expression] that, when analyzed, will behave the same as
  /// `this`, but after visiting it, will verify that the type of the expression
  /// was [expectedType].
  Expression checkType(String expectedType) {
    var location = computeLocation();
    return asExpression(location: location).._expectedType = expectedType;
  }

  /// If `this` is an expression `x`, creates the expression
  /// `x ? ifTrue : ifFalse`.
  Expression conditional(ProtoExpression ifTrue, ProtoExpression ifFalse) {
    var location = computeLocation();
    return new Conditional._(
      asExpression(location: location),
      ifTrue.asExpression(location: location),
      ifFalse.asExpression(location: location),
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x == other`.
  Expression eq(ProtoExpression other) {
    var location = computeLocation();
    return new Equal._(
      asExpression(location: location),
      other.asExpression(location: location),
      false,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x ?? other`.
  Expression ifNull(ProtoExpression other) {
    var location = computeLocation();
    return new IfNull._(
      asExpression(location: location),
      other.asExpression(location: location),
      location: location,
    );
  }

  /// Creates a [Statement] that, when analyzed, will analyze `this`, supplying
  /// a type schema of [typeSchema].
  Statement inTypeSchema(String typeSchema) {
    var location = computeLocation();
    return ExpressionInTypeSchema._(
      asExpression(location: location),
      SharedTypeSchemaView(Type(typeSchema)),
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates a method invocation with `x` as
  /// the target, [name] as the method name, and [arguments] as the method
  /// arguments. Named arguments are not supported.
  Expression invokeMethod(
    String name,
    List<ProtoExpression> arguments, {
    bool isNullAware = false,
  }) {
    var location = computeLocation();
    return new InvokeMethod._(
      asExpression(location: location),
      name,
      [
        for (var argument in arguments)
          argument.asExpression(location: location),
      ],
      isNullAware: isNullAware,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x is typeStr`.
  ///
  /// With [isInverted] set to `true`, creates the expression `x is! typeStr`.
  Expression is_(String typeStr, {bool isInverted = false}) {
    var location = computeLocation();
    return new Is._(
      asExpression(location: location),
      Type(typeStr),
      isInverted,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x is! typeStr`.
  Expression isNot(String typeStr) {
    var location = computeLocation();
    return Is._(
      asExpression(location: location),
      Type(typeStr),
      true,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x != other`.
  Expression notEq(ProtoExpression other) {
    var location = computeLocation();
    return Equal._(
      asExpression(location: location),
      other.asExpression(location: location),
      true,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the expression `x || other`.
  Expression or(ProtoExpression other) {
    var location = computeLocation();
    return new Logical._(
      asExpression(location: location),
      other.asExpression(location: location),
      isAnd: false,
      location: location,
    );
  }

  /// If `this` is an expression `x`, creates the L-value `x.name`.
  PromotableLValue property(String name, {bool isNullAware = false}) {
    var location = computeLocation();
    return new Property._(
      asExpression(location: location),
      name,
      location: location,
      isNullAware: isNullAware,
    );
  }

  /// If `this` is an expression `x`, creates a pseudo-expression that models
  /// evaluation of `x` followed by execution of [stmt].  This can be used to
  /// test that flow analysis is in the correct state after an expression is
  /// visited.
  Expression thenStmt(ProtoStatement stmt) {
    var location = computeLocation();
    return new WrappedExpression._(
      null,
      asExpression(location: location),
      stmt.asStatement(location: location),
      location: location,
    );
  }
}

/// Common functionality shared by constructs that can be used where a statement
/// is expected, in in the pseudo-Dart language used for flow analysis testing.
///
/// The reason this mixin is distinct from the [Statement] class is because both
/// [Expression]s and [Statement]s can be used where a statement is expected
/// (because an [Expression] in a statement context simply becomes an expression
/// statement).
mixin ProtoStatement<Self extends ProtoStatement<dynamic>> {
  /// Converts `this` to a [Statement]. If it's already a [Statement], it is
  /// returned unchanged. If it's an [Expression], it's converted into an
  /// expression statement.
  ///
  /// In general, tests shouldn't need to call this method directly; instead
  /// they should simply be able to use either a [Statement] or an [Expression]
  /// in a context where a statement is expected, and the test infrastructure
  /// will call this getter as needed.
  Statement asStatement({required String location});

  /// Wraps `this` in such a way that, when the test is run, it will verify that
  /// the IR produced matches [expectedIR].
  Self checkIR(String expectedIR);
}

/// Common interface shared by constructs that can be used where a switch head
/// (pattern with optional guard, or `default`) is expected, in the pseudo-Dart
/// language used for flow analysis testing.
abstract class ProtoSwitchHead {
  /// Converts `this` to a [SwitchHead]. If it's already a [SwitchHead], it is
  /// returned unchanged. If it's a [PossiblyGuardedPattern], it's converted
  /// into a [SwitchHeadCase]
  ///
  /// In general, tests shouldn't need to call this getter directly; instead
  /// they should simply be able to use a [Pattern], [GuardedPattern], or
  /// [default_] in a context where a switch head is expected, and the test
  /// infrastructure will call this getter as needed.
  SwitchHead get asSwitchHead;
}

class RecordPattern extends Pattern {
  final List<RecordPatternField> fields;

  RecordPattern._(this.fields, {required super.location}) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) {
    return h.typeAnalyzer.analyzeRecordPatternSchema(fields: fields);
  }

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    for (var field in fields) {
      field.pattern.preVisit(
        visitor,
        variableBinder,
        isInAssignment: isInAssignment,
      );
    }
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var recordPatternResult = h.typeAnalyzer.analyzeRecordPattern(
      context,
      this,
      fields: fields,
    );
    var matchedType =
        recordPatternResult.matchedValueType.unwrapTypeView<Type>();
    var requiredType = recordPatternResult.requiredType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.atom(requiredType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'recordPattern',
      [...List.filled(fields.length, Kind.pattern), Kind.type, Kind.type],
      Kind.pattern,
      names: ['matchedType', 'requiredType'],
      location: location,
    );
    return recordPatternResult;
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    var fieldStrings = [
      for (var field in fields)
        field.pattern._debugString(needsKeywordOrType: needsKeywordOrType),
    ];
    return '(${fieldStrings.join(', ')})';
  }
}

/// A field in object and record patterns.
class RecordPatternField extends Node
    implements shared.RecordPatternField<Node, Pattern> {
  @override
  final String? name;
  @override
  final Pattern pattern;

  RecordPatternField({
    required this.name,
    required this.pattern,
    required super.location,
  }) : super._();

  @override
  Node get node => this;
}

class RelationalPattern extends Pattern {
  final String operator;
  final Expression operand;

  RelationalPattern._(this.operator, this.operand, {required super.location})
    : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) =>
      h.typeAnalyzer.analyzeRelationalPatternSchema();

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    operand.preVisit(visitor);
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeRelationalPattern(
      context,
      this,
      operand,
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      operator,
      [Kind.expression, Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    return analysisResult;
  }

  @override
  _debugString({required bool needsKeywordOrType}) => '$operator $operand';
}

class RestPattern extends Node
    implements ListPatternElement, MapPatternElement {
  final Pattern? subPattern;

  RestPattern._(this.subPattern, {required super.location}) : super._();

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    subPattern?.preVisit(
      visitor,
      variableBinder,
      isInAssignment: isInAssignment,
    );
  }

  @override
  String _debugString({required bool needsKeywordOrType}) {
    var subPattern = this.subPattern;
    if (subPattern == null) {
      return '...';
    } else {
      return '...${subPattern._debugString(needsKeywordOrType: false)}';
    }
  }
}

class Return extends Statement {
  Return._({required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'return;';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeReturnStatement();
    h.irBuilder.apply('return', [], Kind.statement, location: location);
  }
}

/// Representation of an invocation of a function `Second`, defined as follows:
///
///     T second(dynamic x, T y) => y;
class Second extends Expression {
  final Expression first;
  final Expression second;

  Second._(this.first, this.second, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    first.preVisit(visitor);
    second.preVisit(visitor);
  }

  @override
  String toString() => 'second($first, $second)';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    h.typeAnalyzer.analyzeExpression(first, h.operations.unknownType);
    var type = h.typeAnalyzer.analyzeExpression(second, schema);
    h.irBuilder.apply(
      'second',
      [Kind.expression, Kind.expression],
      Kind.expression,
      location: location,
    );
    return ExpressionTypeAnalysisResult(type: type);
  }
}

/// Representation of a statement in the pseudo-Dart language used for flow
/// analysis testing.
abstract class Statement extends Node with ProtoStatement<Statement> {
  /// If non-null, the expected IR that should be produced when this statement
  /// is analyzed.
  String? _expectedIR;

  Statement({required super.location}) : super._();

  @override
  Statement asStatement({required String location}) => this;

  @override
  Statement checkIR(String expectedIR) {
    var location = computeLocation();
    return asStatement(location: location).._expectedIR = expectedIR;
  }

  void preVisit(PreVisitor visitor);

  void visit(Harness h);
}

class SwitchExpression extends Expression {
  final Expression scrutinee;

  final List<ExpressionCase> cases;

  SwitchExpression._(this.scrutinee, this.cases, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    scrutinee.preVisit(visitor);
    for (var case_ in cases) {
      case_._preVisit(visitor);
    }
  }

  @override
  String toString() {
    String body;
    if (cases.isEmpty) {
      body = '{}';
    } else {
      var contents = cases.join(' ');
      body = '{ $contents }';
    }
    return 'switch ($scrutinee) $body';
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeSwitchExpression(
      this,
      scrutinee,
      cases.length,
      schema,
    );
    h.irBuilder.apply(
      'switchExpr',
      [Kind.expression, ...List.filled(cases.length, Kind.expressionCase)],
      Kind.expression,
      location: location,
    );
    return result;
  }
}

abstract class SwitchHead extends Node implements ProtoSwitchHead {
  SwitchHead._({required super.location}) : super._();

  @override
  SwitchHead get asSwitchHead => this;

  SwitchStatementMember then(List<ProtoStatement> body) {
    return SwitchStatementMember._(
      [this],
      Block._(body, location: location),
      hasLabels: false,
      location: location,
    );
  }

  ExpressionCase thenExpr(ProtoExpression body) {
    var location = computeLocation();
    return ExpressionCase._(
      null,
      body.asExpression(location: location),
      location: location,
    );
  }
}

class SwitchHeadCase extends SwitchHead {
  final GuardedPattern guardedPattern;

  SwitchHeadCase._(this.guardedPattern, {required super.location}) : super._();
}

class SwitchHeadDefault extends SwitchHead {
  SwitchHeadDefault._({required super.location}) : super._();
}

class SwitchStatement extends Statement {
  final Expression scrutinee;

  final List<SwitchStatementMember> cases;

  final bool? isLegacyExhaustive;

  final bool? expectHasDefault;

  final bool? expectIsExhaustive;

  final bool? expectLastCaseTerminates;

  final bool? expectRequiresExhaustivenessValidation;

  final String? expectScrutineeType;

  SwitchStatement(
    this.scrutinee,
    this.cases,
    this.isLegacyExhaustive, {
    required super.location,
    required this.expectHasDefault,
    required this.expectIsExhaustive,
    required this.expectLastCaseTerminates,
    required this.expectRequiresExhaustivenessValidation,
    required this.expectScrutineeType,
  });

  @override
  void preVisit(PreVisitor visitor) {
    scrutinee.preVisit(visitor);
    visitor._assignedVariables.beginNode();
    for (var case_ in cases) {
      case_._preVisit(visitor);
    }
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() {
    var isLegacyExhaustive = this.isLegacyExhaustive;
    var exhaustiveness =
        isLegacyExhaustive == null
            ? ''
            : isLegacyExhaustive
            ? '<exhaustive>'
            : '<non-exhaustive>';
    String body;
    if (cases.isEmpty) {
      body = '{}';
    } else {
      var contents = cases.join(' ');
      body = '{ $contents }';
    }
    return 'switch$exhaustiveness ($scrutinee) $body';
  }

  @override
  void visit(Harness h) {
    bool needsLegacyExhaustive = !h.patternsEnabled;
    if (!needsLegacyExhaustive && isLegacyExhaustive != null) {
      fail('isLegacyExhaustive should not be specified at $location');
    } else if (needsLegacyExhaustive && isLegacyExhaustive == null) {
      fail('isLegacyExhaustive should be specified at $location');
    }
    var previousBreakTarget = h.typeAnalyzer._currentBreakTarget;
    h.typeAnalyzer._currentBreakTarget = this;
    var previousContinueTarget = h.typeAnalyzer._currentContinueTarget;
    h.typeAnalyzer._currentContinueTarget = this;
    var analysisResult = h.typeAnalyzer.analyzeSwitchStatement(
      this,
      scrutinee,
      cases.length,
    );
    expect(analysisResult.hasDefault, expectHasDefault ?? anything);
    expect(analysisResult.isExhaustive, expectIsExhaustive ?? anything);
    expect(
      analysisResult.lastCaseTerminates,
      expectLastCaseTerminates ?? anything,
    );
    expect(
      analysisResult.requiresExhaustivenessValidation,
      expectRequiresExhaustivenessValidation ?? anything,
    );
    expect(
      analysisResult.scrutineeType.unwrapTypeView<Type>().type,
      expectScrutineeType ?? anything,
    );
    h.irBuilder.apply(
      'switch',
      [Kind.expression, ...List.filled(cases.length, Kind.statementCase)],
      Kind.statement,
      location: location,
    );
    h.typeAnalyzer._currentBreakTarget = previousBreakTarget;
    h.typeAnalyzer._currentContinueTarget = previousContinueTarget;
  }
}

/// Representation of a single case clause in a switch statement.  Use
/// [PossiblyGuardedPattern.then] or [SwitchHead.then] to create instances of
/// this class.
class SwitchStatementMember extends Node {
  final bool hasLabels;
  final List<SwitchHead> elements;
  final Block body;

  /// These variables are set during pre-visit, and some of them are joins of
  /// pattern variable declarations. We don't know their types until we do
  /// type analysis. So, some of these variables might become unavailable.
  late final Map<String, Var> _candidateVariables;

  SwitchStatementMember._(
    this.elements,
    this.body, {
    required super.location,
    required this.hasLabels,
  }) : super._();

  void _preVisit(PreVisitor visitor) {
    var variableBinder = _VariableBinder(visitor);
    variableBinder.switchStatementSharedCaseScopeStart(this);
    for (SwitchHead element in elements) {
      if (element is SwitchHeadCase) {
        variableBinder.casePatternStart();
        element.guardedPattern.pattern.preVisit(
          visitor,
          variableBinder,
          isInAssignment: false,
        );
        element.guardedPattern.guard?.preVisit(visitor);
        element.guardedPattern.variables = variableBinder.casePatternFinish(
          sharedCaseScopeKey: this,
        );
      } else {
        variableBinder.switchStatementSharedCaseScopeEmpty(this);
      }
    }
    if (hasLabels) {
      variableBinder.switchStatementSharedCaseScopeEmpty(this);
    }
    _candidateVariables = variableBinder.switchStatementSharedCaseScopeFinish(
      this,
    );
    body.preVisit(visitor);
  }
}

class This extends Expression {
  This._({required super.location});

  @override
  void preVisit(PreVisitor visitor) {}

  @override
  String toString() => 'this';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeThis(this);
    h.irBuilder.atom('this', Kind.expression, location: location);
    return result;
  }
}

class ThisOrSuperProperty extends PromotableLValue {
  final String propertyName;
  final bool isSuperAccess;

  ThisOrSuperProperty._(
    this.propertyName, {
    required super.location,
    required this.isSuperAccess,
  }) : super._();

  @override
  void preVisit(
    PreVisitor visitor, {
    _LValueDisposition disposition = _LValueDisposition.read,
  }) {}

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeThisOrSuperPropertyGet(
      this,
      propertyName,
      isSuperAccess: isSuperAccess,
    );
    var thisOrSuper = isSuperAccess ? 'super' : 'this';
    h.irBuilder.atom(
      '$thisOrSuper.$propertyName',
      Kind.expression,
      location: location,
    );
    return result;
  }

  @override
  Type? _getPromotedType(Harness h) {
    var thisOrSuper = isSuperAccess ? 'super' : 'this';
    h.irBuilder.atom(
      '$thisOrSuper.$propertyName',
      Kind.expression,
      location: location,
    );
    var member = h.typeAnalyzer._lookupMember(h._thisType!, propertyName);
    return h.flow
        .promotedPropertyType(
          isSuperAccess
              ? SuperPropertyTarget.singleton
              : ThisPropertyTarget.singleton,
          propertyName,
          member,
          SharedTypeView(member!._type),
        )
        ?.unwrapTypeView();
  }

  @override
  void _visitPostIncDec(
    Harness h,
    Expression postIncDecExpression,
    Type writtenType,
  ) {
    // No flow analysis impact
  }

  @override
  void _visitWrite(
    Harness h,
    Expression assignmentExpression,
    Type writtenType,
    Expression? rhs,
  ) {
    // No flow analysis impact
  }
}

class Throw extends Expression {
  final Expression operand;

  Throw._(this.operand, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    operand.preVisit(visitor);
  }

  @override
  String toString() => 'throw ...';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    return h.typeAnalyzer.analyzeThrow(this, operand);
  }
}

abstract class TryBuilder {
  TryStatement catch_({
    Var? exception,
    Var? stackTrace,
    required List<ProtoStatement> body,
  });

  Statement finally_(List<ProtoStatement> statements);
}

abstract class TryStatement extends Statement implements TryBuilder {
  TryStatement._({required super.location});
}

class TryStatementImpl extends TryStatement {
  final Statement body;
  final List<CatchClause> catches;
  final Statement? finallyStatement;

  TryStatementImpl(
    this.body,
    this.catches,
    this.finallyStatement, {
    required super.location,
  }) : super._();

  @override
  TryStatement catch_({
    Var? exception,
    Var? stackTrace,
    required List<ProtoStatement> body,
  }) {
    assert(finallyStatement == null, 'catch after finally');
    return TryStatementImpl(
      this.body,
      [
        ...catches,
        CatchClause._(
          Block._(body, location: computeLocation()),
          exception,
          stackTrace,
        ),
      ],
      null,
      location: location,
    );
  }

  @override
  Statement finally_(List<ProtoStatement> statements) {
    assert(finallyStatement == null, 'multiple finally clauses');
    return TryStatementImpl(
      body,
      catches,
      Block._(statements, location: computeLocation()),
      location: location,
    );
  }

  @override
  void preVisit(PreVisitor visitor) {
    if (finallyStatement != null) {
      visitor._assignedVariables.beginNode();
    }
    if (catches.isNotEmpty) {
      visitor._assignedVariables.beginNode();
    }
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(body);
    for (var catch_ in catches) {
      catch_._preVisit(visitor);
    }
    if (finallyStatement != null) {
      if (catches.isNotEmpty) {
        visitor._assignedVariables.endNode(this);
      }
      finallyStatement!.preVisit(visitor);
    }
  }

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeTryStatement(this, body, catches, finallyStatement);
    h.irBuilder.apply(
      'try',
      [
        Kind.statement,
        ...List.filled(catches.length, Kind.statement),
        Kind.statement,
      ],
      Kind.statement,
      location: location,
    );
  }
}

/// Variant of [Label] that causes `null` to be passed to `handleBreak` or
/// `handleContinue`.
class UnboundLabel extends Label {
  UnboundLabel._() : super._(location: computeLocation());

  @override
  Statement thenStmt(Statement statement) {
    fail("Unbound labels can't be bound");
  }

  @override
  String toString() => '<UNBOUND LABEL>';

  @override
  Statement? _getBinding() => null;
}

/// Representation of a local variable in the pseudo-Dart language used for flow
/// analysis testing.
class Var extends Node
    with
        ProtoStatement<Expression>,
        ProtoCollectionElement<Expression>,
        ProtoExpression
    implements Promotable {
  final String name;
  bool isFinal;

  /// The type of the variable, or `null` if it is not yet known.
  Type? _type;

  /// Identifier for this variable in IR.  This allows distinct variables with
  /// the same name to be distinguished.
  final String identity;

  /// The [PatternVariableJoin] that this variable is a component of, if any.
  PatternVariableJoin? _joinedVar;

  Var(this.name, {this.isFinal = false, String? identity, String? location})
    : identity = identity ?? name,
      super._(location: location ?? computeLocation());

  JoinedPatternVariableInconsistency get inconsistency {
    return JoinedPatternVariableInconsistency.none;
  }

  /// The string that should be used to check variables in a set.
  String get stringToCheckVariables => identity;

  /// Gets the type if known; otherwise throws an exception.
  Type get type {
    if (_type == null) {
      throw 'Type not yet known';
    } else {
      return _type!;
    }
  }

  set type(Type value) {
    if (_type != null) {
      throw 'Type already set';
    }
    _type = value;
  }

  @override
  LValue asExpression({required String location}) =>
      new VariableReference._(this, null, location: location);

  Pattern pattern({String? type, String? expectInferredType}) =>
      new VariablePattern._(
        type == null ? null : Type(type),
        this,
        expectInferredType,
        location: computeLocation(),
      );

  /// Creates an expression representing a postfix increment or decrement
  /// operation applied to this variable.
  Expression postIncDec() {
    var location = computeLocation();
    return new PostIncDec(
      new VariableReference._(this, null, location: location),
      location: location,
    );
  }

  @override
  void preVisit(PreVisitor visitor) {}

  /// Creates an expression representing a read of this variable, which as a
  /// side effect will call the given callback with the returned promoted type.
  Expression readAndCheckPromotedType(void Function(Type?) callback) =>
      new VariableReference._(this, callback, location: computeLocation());

  @override
  String toString() => 'var $name';

  /// Creates an expression representing a write to this variable.
  Expression write(ProtoExpression? value) {
    var location = computeLocation();
    return new Write(
      new VariableReference._(this, null, location: location),
      value?.asExpression(location: location),
      location: location,
    );
  }

  @override
  Type? _getPromotedType(Harness h) {
    h.irBuilder.atom(name, Kind.expression, location: location);
    return h.flow.promotedType(this)?.unwrapTypeView();
  }
}

class VariableDeclaration extends Statement {
  final Var variable;
  final bool isLate;
  final bool isFinal;
  final Type? declaredType;
  final Expression? initializer;
  final String? expectInferredType;

  VariableDeclaration._({
    required super.location,
    required this.variable,
    required this.isLate,
    required this.isFinal,
    required this.declaredType,
    required this.initializer,
    required this.expectInferredType,
  });

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.declare(variable);
    if (isLate) {
      visitor._assignedVariables.beginNode();
    }
    initializer?.preVisit(visitor);
    if (isLate) {
      visitor._assignedVariables.endNode(this);
    }
  }

  @override
  String toString() {
    var parts = <String>[
      if (isLate) 'late',
      if (isFinal) 'final',
      if (declaredType != null) declaredType!.type else if (!isFinal) 'var',
      variable.name,
      if (expectInferredType != null) '(expected type $expectInferredType)',
      if (initializer != null) '= $initializer',
    ];
    return '${parts.join(' ')};';
  }

  @override
  void visit(Harness h) {
    String irName;
    List<Kind> argKinds;
    List<String> names = const [];
    var initializer = this.initializer;
    h.irBuilder.atom(variable.name, Kind.variable, location: location);
    Type staticType;
    if (initializer == null) {
      // Use the shared logic for analyzing uninitialized variable
      // declarations.
      staticType =
          h.typeAnalyzer
              .analyzeUninitializedVariableDeclaration(
                this,
                variable,
                declaredType?.wrapSharedTypeView(),
                isFinal: isFinal,
              )
              .unwrapTypeView();
      h.irBuilder.atom(staticType.type, Kind.type, location: location);
      irName = 'declare';
      argKinds = [Kind.variable, Kind.type];
      names = ['staticType'];
    } else {
      // There's no shared logic for analyzing initialized variable
      // declarations, so analyze the declaration directly.
      if (isLate) h.flow.lateInitializer_begin(this);
      var initializerType =
          h.typeAnalyzer
              .analyzeExpression(
                initializer,
                declaredType?.wrapSharedTypeSchemaView() ??
                    h.operations.unknownType,
              )
              .unwrapTypeView<Type>();
      if (isLate) h.flow.lateInitializer_end();
      staticType =
          variable.type =
              declaredType ??
              h.typeAnalyzer
                  .variableTypeFromInitializerType(
                    initializerType.wrapSharedTypeView(),
                  )
                  .unwrapTypeView();
      h.flow.declare(variable, SharedTypeView(staticType), initialized: true);
      h.flow.initialize(
        variable,
        SharedTypeView(initializerType),
        initializer,
        isFinal: isFinal,
        isLate: isLate,
        isImplicitlyTyped: declaredType == null,
      );
      h.irBuilder.atom(initializerType.type, Kind.type, location: location);
      h.irBuilder.atom(staticType.type, Kind.type, location: location);
      irName = 'declare';
      argKinds = [Kind.variable, Kind.expression, Kind.type, Kind.type];
      names = ['initializerType', 'staticType'];
    }
    // Finally, double check the inferred variable type, if necessary for the
    // test.
    var expectInferredType = this.expectInferredType;
    if (expectInferredType != null) {
      expect(staticType.type, expectInferredType, reason: 'at $location');
    }
    h.irBuilder.apply(
      [irName, if (isLate) 'late', if (isFinal) 'final'].join('_'),
      argKinds,
      Kind.statement,
      location: location,
      names: names,
    );
  }
}

class VariablePattern extends Pattern {
  final Type? declaredType;

  final Var variable;

  final String? expectInferredType;

  late bool isAssignedVariable;

  VariablePattern._(
    this.declaredType,
    this.variable,
    this.expectInferredType, {
    required super.location,
  }) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) {
    if (isAssignedVariable) {
      return h.typeAnalyzer.analyzeAssignedVariablePatternSchema(variable);
    } else {
      return h.typeAnalyzer.analyzeDeclaredVariablePatternSchema(
        declaredType?.wrapSharedTypeView(),
      );
    }
  }

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {
    var variable = this.variable;
    isAssignedVariable = isInAssignment;
    if (!isAssignedVariable && variableBinder.add(variable.name, variable)) {
      visitor._assignedVariables.declare(variable);
    }
    if (isAssignedVariable) {
      assert(
        declaredType == null,
        "Variables in pattern assignments can't have declared types",
      );
    }
  }

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    if (isAssignedVariable) {
      var analysisResult = h.typeAnalyzer.analyzeAssignedVariablePattern(
        context,
        this,
        variable,
      );
      h.typeAnalyzer.handleAssignedVariablePattern(this);
      return analysisResult;
    } else {
      var declaredVariablePatternResult = h.typeAnalyzer
          .analyzeDeclaredVariablePattern(
            context,
            this,
            variable,
            variable.name,
            declaredType?.wrapSharedTypeView(),
          );
      var matchedType =
          declaredVariablePatternResult.matchedValueType.unwrapTypeView<Type>();
      var staticType =
          declaredVariablePatternResult.staticType.unwrapTypeView<Type>();
      h.typeAnalyzer.handleDeclaredVariablePattern(
        this,
        matchedType: matchedType,
        staticType: staticType,
      );
      return declaredVariablePatternResult;
    }
  }

  @override
  _debugString({required bool needsKeywordOrType}) => [
    if (declaredType != null)
      declaredType!.type
    else if (needsKeywordOrType)
      'var',
    variable.name,
    if (expectInferredType != null) '(expected type $expectInferredType)',
  ].join(' ');
}

class VariableReference extends LValue {
  final Var variable;

  final void Function(Type?)? callback;

  VariableReference._(this.variable, this.callback, {required super.location})
    : super._();

  @override
  void preVisit(
    PreVisitor visitor, {
    _LValueDisposition disposition = _LValueDisposition.read,
  }) {
    if (disposition != _LValueDisposition.write) {
      visitor._assignedVariables.read(variable);
    }
    if (disposition != _LValueDisposition.read) {
      visitor._assignedVariables.write(variable);
    }
  }

  @override
  String toString() => variable.name;

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var result = h.typeAnalyzer.analyzeVariableGet(this, variable, callback);
    h.irBuilder.atom(variable.name, Kind.expression, location: location);
    return result;
  }

  @override
  void _visitPostIncDec(
    Harness h,
    Expression postIncDecExpression,
    Type writtenType,
  ) {
    h.flow.postIncDec(
      postIncDecExpression,
      variable,
      SharedTypeView(writtenType),
    );
  }

  @override
  void _visitWrite(
    Harness h,
    Expression assignmentExpression,
    Type writtenType,
    Expression? rhs,
  ) {
    h.flow.write(
      assignmentExpression,
      variable,
      SharedTypeView(writtenType),
      rhs,
    );
  }
}

class While extends Statement {
  final Expression condition;
  final Statement body;

  While._(this.condition, this.body, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    visitor._assignedVariables.beginNode();
    condition.preVisit(visitor);
    body.preVisit(visitor);
    visitor._assignedVariables.endNode(this);
  }

  @override
  String toString() => 'while ($condition) $body';

  @override
  void visit(Harness h) {
    h.typeAnalyzer.analyzeWhileLoop(this, condition, body);
    h.irBuilder.apply(
      'while',
      [Kind.expression, Kind.statement],
      Kind.statement,
      location: location,
    );
  }
}

class WildcardPattern extends Pattern {
  final Type? declaredType;

  final String? expectInferredType;

  WildcardPattern._({
    required this.declaredType,
    required this.expectInferredType,
    required super.location,
  }) : super._();

  @override
  SharedTypeSchemaView computeSchema(Harness h) {
    return h.typeAnalyzer.analyzeWildcardPatternSchema(
      declaredType: declaredType?.wrapSharedTypeView(),
    );
  }

  @override
  void preVisit(
    PreVisitor visitor,
    VariableBinder<Node, Var> variableBinder, {
    required bool isInAssignment,
  }) {}

  @override
  PatternResult visit(Harness h, SharedMatchContext context) {
    var analysisResult = h.typeAnalyzer.analyzeWildcardPattern(
      context: context,
      node: this,
      declaredType: declaredType?.wrapSharedTypeView(),
    );
    var matchedType = analysisResult.matchedValueType.unwrapTypeView<Type>();
    h.irBuilder.atom(matchedType.type, Kind.type, location: location);
    h.irBuilder.apply(
      'wildcardPattern',
      [Kind.type],
      Kind.pattern,
      names: ['matchedType'],
      location: location,
    );
    var expectInferredType = this.expectInferredType;
    if (expectInferredType != null) {
      expect(matchedType.type, expectInferredType, reason: 'at $location');
    }
    return analysisResult;
  }

  @override
  _debugString({required bool needsKeywordOrType}) => [
    if (declaredType != null) declaredType!.type,
    '_',
    if (expectInferredType != null) '(expected type $expectInferredType)',
  ].join(' ');
}

class WrappedExpression extends Expression {
  final Statement? before;
  final Expression expr;
  final Statement? after;

  WrappedExpression._(
    this.before,
    this.expr,
    this.after, {
    required super.location,
  });

  @override
  void preVisit(PreVisitor visitor) {
    before?.preVisit(visitor);
    expr.preVisit(visitor);
    after?.preVisit(visitor);
  }

  @override
  String toString() {
    var s = StringBuffer('(');
    if (before != null) {
      s.write('($before) ');
    }
    s.write(expr);
    if (after != null) {
      s.write(' ($after)');
    }
    s.write(')');
    return s.toString();
  }

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    late MiniIRTmp beforeTmp;
    if (before != null) {
      h.typeAnalyzer.dispatchStatement(before!);
      h.irBuilder.apply(
        'expr',
        [Kind.statement],
        Kind.expression,
        location: location,
      );
      beforeTmp = h.irBuilder.allocateTmp(location: location);
    }
    var type = h.typeAnalyzer.analyzeExpression(expr, h.operations.unknownType);
    if (after != null) {
      var exprTmp = h.irBuilder.allocateTmp(location: location);
      h.typeAnalyzer.dispatchStatement(after!);
      h.irBuilder.apply(
        'expr',
        [Kind.statement],
        Kind.expression,
        location: location,
      );
      var afterTmp = h.irBuilder.allocateTmp(location: location);
      h.irBuilder.readTmp(exprTmp, location: location);
      h.irBuilder.let(afterTmp, location: location);
      h.irBuilder.let(exprTmp, location: location);
    }
    h.flow.forwardExpression(this, expr);
    if (before != null) {
      h.irBuilder.let(beforeTmp, location: location);
    }
    return new ExpressionTypeAnalysisResult(type: type);
  }
}

class Write extends Expression {
  final LValue lhs;
  final Expression? rhs;

  Write(this.lhs, this.rhs, {required super.location});

  @override
  void preVisit(PreVisitor visitor) {
    lhs.preVisit(
      visitor,
      disposition:
          rhs == null ? _LValueDisposition.readWrite : _LValueDisposition.write,
    );
    rhs?.preVisit(visitor);
  }

  @override
  String toString() => '$lhs = $rhs';

  @override
  ExpressionTypeAnalysisResult visit(Harness h, SharedTypeSchemaView schema) {
    var rhs = this.rhs;
    Type type;
    if (rhs == null) {
      // We are simulating an increment/decrement operation.
      // TODO(paulberry): Make a separate node type for this.
      type =
          h.typeAnalyzer
              .analyzeExpression(lhs, h.operations.unknownType)
              .unwrapTypeView();
    } else {
      type =
          h.typeAnalyzer
              .analyzeExpression(rhs, h.operations.unknownType)
              .unwrapTypeView();
    }
    lhs._visitWrite(h, this, type, rhs);
    // TODO(paulberry): null shorting
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }
}

/// Enum representing the different ways an [LValue] might be used.
enum _LValueDisposition {
  /// The [LValue] is being read from only, not written to.  This happens if it
  /// appears in a place where an ordinary expression is expected.
  read,

  /// The [LValue] is being written to only, not read from.  This happens if it
  /// appears on the left hand side of `=`.
  write,

  /// The [LValue] is being both read from and written to.  This happens if it
  /// appears on the left and side of `op=` (where `op` is some operator), or as
  /// the target of `++` or `--`.
  readWrite,
}

class _MiniAstErrors
    implements
        TypeAnalyzerErrors<
          Node,
          Statement,
          Expression,
          Var,
          SharedTypeView,
          Pattern,
          void
        >,
        VariableBinderErrors<Node, Var> {
  final Set<String> _accumulatedErrors = {};

  /// If [assertInErrorRecovery] is called prior to any errors being reported,
  /// the stack trace is captured and stored in this variable, so that if no
  /// errors are reported by the end of running the test, we can use it to
  /// highlight the point of failure.
  StackTrace? _assertInErrorRecoveryStack;

  @override
  void assertInErrorRecovery() {
    if (_accumulatedErrors.isEmpty) {
      _assertInErrorRecoveryStack ??= StackTrace.current;
    }
  }

  @override
  void caseExpressionTypeMismatch({
    required Expression scrutinee,
    required Expression caseExpression,
    required SharedTypeView scrutineeType,
    required SharedTypeView caseExpressionType,
  }) {
    _recordError('caseExpressionTypeMismatch', {
      'scrutinee': scrutinee,
      'caseExpression': caseExpression,
      'scrutineeType': scrutineeType,
      'caseExpressionType': caseExpressionType,
    });
  }

  @override
  void duplicateAssignmentPatternVariable({
    required Var variable,
    required Pattern original,
    required Pattern duplicate,
  }) {
    _recordError('duplicateAssignmentPatternVariable', {
      'variable': variable,
      'original': original,
      'duplicate': duplicate,
    });
  }

  @override
  void duplicateRecordPatternField({
    required Pattern objectOrRecordPattern,
    required String name,
    required covariant RecordPatternField original,
    required covariant RecordPatternField duplicate,
  }) {
    _recordError('duplicateRecordPatternField', {
      'objectOrRecordPattern': objectOrRecordPattern,
      'name': name,
      'original': original,
      'duplicate': duplicate,
    });
  }

  @override
  void duplicateRestPattern({
    required Pattern mapOrListPattern,
    required Node original,
    required Node duplicate,
  }) {
    _recordError('duplicateRestPattern', {
      'mapOrListPattern': mapOrListPattern,
      'original': original,
      'duplicate': duplicate,
    });
  }

  @override
  void duplicateVariablePattern({
    required String name,
    required Var original,
    required Var duplicate,
  }) {
    _recordError('duplicateVariablePattern', {
      'name': name,
      'original': original,
      'duplicate': duplicate,
    });
  }

  @override
  void emptyMapPattern({required Pattern pattern}) {
    _recordError('emptyMapPattern', {'pattern': pattern});
  }

  @override
  void inconsistentJoinedPatternVariable({
    required covariant PatternVariableJoin variable,
    required Var component,
  }) {
    _recordError('inconsistentJoinedPatternVariable', {
      'variable': '$variable',
      'component': component,
    });
  }

  @override
  void logicalOrPatternBranchMissingVariable({
    required Node node,
    required bool hasInLeft,
    required String name,
    required Var variable,
  }) {
    _recordError('logicalOrPatternBranchMissingVariable', {
      'node': node,
      'hasInLeft': hasInLeft,
      'name': name,
      'variable': variable,
    });
  }

  @override
  void matchedTypeIsStrictlyNonNullable({
    required Pattern pattern,
    required SharedTypeView matchedType,
  }) {
    _recordError('matchedTypeIsStrictlyNonNullable', {
      'pattern': pattern,
      'matchedType': matchedType,
    });
  }

  @override
  void matchedTypeIsSubtypeOfRequired({
    required Pattern pattern,
    required SharedTypeView matchedType,
    required SharedTypeView requiredType,
  }) {
    _recordError('matchedTypeIsSubtypeOfRequired', {
      'pattern': pattern,
      'matchedType': matchedType,
      'requiredType': requiredType,
    });
  }

  @override
  void nonBooleanCondition({required Expression node}) {
    _recordError('nonBooleanCondition', {'node': node});
  }

  @override
  void patternForInExpressionIsNotIterable({
    required Node node,
    required Expression expression,
    required SharedTypeView expressionType,
  }) {
    _recordError('patternForInExpressionIsNotIterable', {
      'node': node,
      'expression': expression,
      'expressionType': expressionType,
    });
  }

  @override
  void patternTypeMismatchInIrrefutableContext({
    required Node pattern,
    required Node context,
    required SharedTypeView matchedType,
    required SharedTypeView requiredType,
  }) {
    _recordError('patternTypeMismatchInIrrefutableContext', {
      'pattern': pattern,
      'context': context,
      'matchedType': matchedType,
      'requiredType': requiredType,
    });
  }

  @override
  void refutablePatternInIrrefutableContext({
    required Node pattern,
    required Node context,
  }) {
    _recordError('refutablePatternInIrrefutableContext', {
      'pattern': pattern,
      'context': context,
    });
  }

  @override
  void relationalPatternOperandTypeNotAssignable({
    required Pattern pattern,
    required SharedTypeView operandType,
    required SharedTypeView parameterType,
  }) {
    _recordError('relationalPatternOperandTypeNotAssignable', {
      'pattern': pattern,
      'operandType': operandType,
      'parameterType': parameterType,
    });
  }

  @override
  void relationalPatternOperatorReturnTypeNotAssignableToBool({
    required Pattern pattern,
    required SharedTypeView returnType,
  }) {
    _recordError('relationalPatternOperatorReturnTypeNotAssignableToBool', {
      'pattern': pattern,
      'returnType': returnType,
    });
  }

  @override
  void restPatternInMap({required Pattern node, required Node element}) {
    _recordError('restPatternInMap', {'node': node, 'element': element});
  }

  @override
  void switchCaseCompletesNormally({
    required covariant SwitchStatement node,
    required int caseIndex,
  }) {
    _recordError('switchCaseCompletesNormally', {
      'node': node,
      'caseIndex': caseIndex,
    });
  }

  @override
  void unnecessaryWildcardPattern({
    required Pattern pattern,
    required UnnecessaryWildcardKind kind,
  }) {
    _recordError('unnecessaryWildcardPattern', {
      'pattern': pattern,
      'kind': kind,
    });
  }

  void _recordError(String name, Map<String, Object?> namedArguments) {
    String argumentStr(Object? argument) {
      if (argument is bool) {
        return '$argument';
      } else if (argument is int) {
        return '$argument';
      } else if (argument is Enum) {
        return argument.name;
      } else if (argument is Node) {
        return argument.errorId;
      } else if (argument is Type) {
        return argument.type;
      } else {
        return argument as String;
      }
    }

    String argumentsStr = namedArguments.entries
        .map((entry) {
          return '${entry.key}: ${argumentStr(entry.value)}';
        })
        .join(', ');

    var errorText = '$name($argumentsStr)';

    _assertInErrorRecoveryStack = null;
    if (!_accumulatedErrors.add(errorText)) {
      fail('Same error reported twice: $errorText');
    }
  }
}

class _MiniAstTypeAnalyzer
    with
        TypeAnalyzer<
          Node,
          Statement,
          Expression,
          Var,
          Pattern,
          void,
          Type,
          String
        >,
        NullShortingMixin<MiniIRTmp, Expression, Var, SharedTypeView> {
  final Harness _harness;

  @override
  final _MiniAstErrors errors = _MiniAstErrors();

  Statement? _currentBreakTarget;

  Statement? _currentContinueTarget;

  final _irBuilder = MiniIRBuilder();

  @override
  final TypeAnalyzerOptions typeAnalyzerOptions;

  /// The temporary variable used in the IR to represent the target of the
  /// innermost enclosing cascade expression, or `null` if no cascade expression
  /// is currently being visited.
  MiniIRTmp? _currentCascadeTargetIR;

  /// The type of the target of the innermost enclosing cascade expression
  /// (promoted to non-nullable, if it's a null-aware cascade), or `null` if no
  /// cascade expression is currently being visited.
  SharedTypeView? _currentCascadeTargetType;

  _MiniAstTypeAnalyzer(this._harness, this.typeAnalyzerOptions);

  @override
  FlowAnalysis<Node, Statement, Expression, Var, SharedTypeView> get flow =>
      _harness.flow;

  Type get nullType => NullType.instance;

  @override
  MiniAstOperations get operations => _harness.operations;

  Type get thisType => _harness._thisType!;

  void analyzeAssertStatement(
    Statement node,
    Expression condition,
    Expression? message,
  ) {
    flow.assert_begin();
    analyzeExpression(condition, operations.unknownType);
    flow.assert_afterCondition(condition);
    if (message != null) {
      analyzeExpression(message, operations.unknownType);
    } else {
      handleNoMessage(node);
    }
    flow.assert_end();
  }

  ExpressionTypeAnalysisResult analyzeBinaryExpression(
    Expression node,
    Expression lhs,
    String operatorName,
    Expression rhs,
  ) {
    bool isEquals = false;
    bool isNot = false;
    bool isLogical = false;
    bool isAnd = false;
    switch (operatorName) {
      case '==':
        isEquals = true;
        break;
      case '!=':
        isEquals = true;
        isNot = true;
        operatorName = '==';
        break;
      case '&&':
        isLogical = true;
        isAnd = true;
        break;
      case '||':
        isLogical = true;
        break;
    }
    if (operatorName == '==') {
      isEquals = true;
    } else if (operatorName == '!=') {
      isEquals = true;
      isNot = true;
      operatorName = '==';
    }
    if (isLogical) {
      flow.logicalBinaryOp_begin();
    }
    var leftType = analyzeExpression(lhs, operations.unknownType);
    ExpressionInfo<SharedTypeView>? leftInfo;
    if (isEquals) {
      leftInfo = flow.equalityOperand_end(lhs);
    } else if (isLogical) {
      flow.logicalBinaryOp_rightBegin(lhs, node, isAnd: isAnd);
    }
    var rightType = analyzeExpression(rhs, operations.unknownType);
    if (isEquals) {
      flow.equalityOperation_end(
        node,
        leftInfo,
        leftType,
        flow.equalityOperand_end(rhs),
        rightType,
        notEqual: isNot,
      );
    } else if (isLogical) {
      flow.logicalBinaryOp_end(node, rhs, isAnd: isAnd);
    }
    return new ExpressionTypeAnalysisResult(type: operations.boolType);
  }

  void analyzeBlock(Iterable<Statement> statements) {
    for (var statement in statements) {
      dispatchStatement(statement);
    }
  }

  Type analyzeBoolLiteral(Expression node, bool value) {
    flow.booleanLiteral(node, value);
    return operations.boolType.unwrapTypeView();
  }

  void analyzeBreakStatement(Statement? target) {
    flow.handleBreak(target);
  }

  ExpressionTypeAnalysisResult analyzeConditionalExpression(
    Expression node,
    Expression condition,
    Expression ifTrue,
    Expression ifFalse,
  ) {
    flow.conditional_conditionBegin();
    analyzeExpression(condition, operations.unknownType);
    flow.conditional_thenBegin(condition, node);
    var ifTrueType = analyzeExpression(ifTrue, operations.unknownType);
    flow.conditional_elseBegin(ifTrue, ifTrueType);
    var ifFalseType = analyzeExpression(ifFalse, operations.unknownType);
    var lubType = operations.lub(ifTrueType, ifFalseType);
    flow.conditional_end(node, lubType, ifFalse, ifFalseType);
    return new ExpressionTypeAnalysisResult(type: lubType);
  }

  void analyzeContinueStatement(Statement? target) {
    flow.handleContinue(target);
  }

  void analyzeDoLoop(Statement node, Statement body, Expression condition) {
    flow.doStatement_bodyBegin(node);
    _visitLoopBody(node, body);
    flow.doStatement_conditionBegin();
    analyzeExpression(condition, operations.unknownType);
    flow.doStatement_end(condition);
  }

  ExpressionTypeAnalysisResult analyzeDotShorthandExpression(
    Expression expression,
    SharedTypeSchemaView schema,
  ) {
    var type = analyzeDotShorthand(expression, schema);
    return new ExpressionTypeAnalysisResult(type: type);
  }

  ExpressionTypeAnalysisResult analyzeDotShorthandHeadExpression(
    Expression node,
    String name,
    SharedTypeSchemaView schema,
  ) {
    _irBuilder.atom(name, Kind.expression, location: node.location);
    return new ExpressionTypeAnalysisResult(
      type: SharedTypeView(getDotShorthandContext().unwrapTypeSchemaView()),
    );
  }

  void analyzeExpressionStatement(Expression expression) {
    analyzeExpression(expression, operations.unknownType);
  }

  ExpressionTypeAnalysisResult analyzeIfNullExpression(
    Expression node,
    Expression lhs,
    Expression rhs,
  ) {
    var leftType = analyzeExpression(lhs, operations.unknownType);
    flow.ifNullExpression_rightBegin(lhs, leftType);
    var rightType = analyzeExpression(rhs, operations.unknownType);
    flow.ifNullExpression_end();
    return new ExpressionTypeAnalysisResult(
      type: operations.lub(
        flow.operations.promoteToNonNull(leftType),
        rightType,
      ),
    );
  }

  void analyzeLabeledStatement(Statement node, Statement body) {
    flow.labeledStatement_begin(node);
    dispatchStatement(body);
    flow.labeledStatement_end();
  }

  ExpressionTypeAnalysisResult analyzeLogicalNot(
    Expression node,
    Expression expression,
  ) {
    analyzeExpression(expression, operations.unknownType);
    flow.logicalNot_end(node, expression);
    return new ExpressionTypeAnalysisResult(type: operations.boolType);
  }

  /// Invokes the appropriate flow analysis methods, and creates the IR
  /// representation, for a method invocation. [node] is the full method
  /// invocation expression, [target] is the expression before the `.` (or
  /// `null` in case of a cascaded method invocation), [methodName] is the name
  /// of the method being invoked, and [arguments] is the list of argument
  /// expressions.
  ///
  /// Named arguments are not supported.
  ExpressionTypeAnalysisResult analyzeMethodInvocation(
    Expression node,
    Expression? target,
    String methodName,
    List<Expression> arguments, {
    required bool isNullAware,
  }) {
    // Analyze the target, generate its IR, and look up the method's type.
    var methodType = _handlePropertyTargetAndMemberLookup(
      null,
      target,
      methodName,
      location: node.location,
      isNullAware: isNullAware,
    );
    var returnType = operations.dynamicType.unwrapTypeView();
    if (methodType is FunctionType) {
      returnType = methodType.returnType;
      if (methodType.namedParameters.isNotEmpty) {
        throw UnimplementedError('Named parameters are not supported yet');
      } else if (methodType.requiredPositionalParameterCount !=
          methodType.positionalParameters.length) {
        throw UnimplementedError(
          'Optional positional parameters are not supported yet',
        );
      }
    }
    // Recursively analyze each argument.
    var inputKinds = [Kind.expression];
    for (var i = 0; i < arguments.length; i++) {
      inputKinds.add(Kind.expression);
      analyzeExpression(
        arguments[i],
        methodType is FunctionType && !methodType.isQuestionType
            ? operations.typeToSchema(
              SharedTypeView(methodType.positionalParameters[i]),
            )
            : operations.unknownType,
      );
    }
    // Form the IR for the member invocation.
    _harness.irBuilder.apply(
      methodName,
      inputKinds,
      Kind.expression,
      location: node.location,
    );
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(returnType));
  }

  ExpressionTypeAnalysisResult analyzeNonNullAssert(
    Expression node,
    Expression expression,
  ) {
    var type = analyzeExpression(
      expression,
      operations.unknownType,
      continueNullShorting: true,
    );
    flow.nonNullAssert_end(expression);
    return new ExpressionTypeAnalysisResult(
      type: flow.operations.promoteToNonNull(type),
    );
  }

  ExpressionTypeAnalysisResult analyzeNullLiteral(Expression node) {
    flow.nullLiteral(node, SharedTypeView(nullType));
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(nullType));
  }

  ExpressionTypeAnalysisResult analyzeParenthesizedExpression(
    Expression node,
    Expression expression,
    SharedTypeSchemaView schema,
  ) {
    var type = analyzeExpression(expression, schema);
    flow.parenthesizedExpression(node, expression);
    return new ExpressionTypeAnalysisResult(type: type);
  }

  /// Invokes the appropriate flow analysis methods, and creates the IR
  /// representation, for a property get. [node] is the full property get
  /// expression, [target] is the expression before the `.` (or `null` in the
  /// case of a cascaded property get), and [propertyName] is the name of the
  /// property being accessed.
  ///
  /// Null-aware property accesses are not supported.
  ExpressionTypeAnalysisResult analyzePropertyGet(
    Expression node,
    Expression? target,
    String propertyName, {
    required bool isNullAware,
  }) {
    // Analyze the target, generate its IR, and look up the property's type.
    var propertyType = _handlePropertyTargetAndMemberLookup(
      node,
      target,
      propertyName,
      location: node.location,
      isNullAware: isNullAware,
    );
    // Build the property get IR.
    _harness.irBuilder.propertyGet(propertyName, location: node.location);
    // TODO(paulberry): handle null shorting
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(propertyType));
  }

  void analyzeReturnStatement() {
    flow.handleExit();
  }

  ExpressionTypeAnalysisResult analyzeThis(Expression node) {
    var thisType = this.thisType;
    flow.thisOrSuper(node, SharedTypeView(thisType), isSuper: false);
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(thisType));
  }

  ExpressionTypeAnalysisResult analyzeThisOrSuperPropertyGet(
    Expression node,
    String propertyName, {
    required bool isSuperAccess,
  }) {
    var member = _lookupMember(thisType, propertyName);
    var memberType = member?._type ?? operations.dynamicType.unwrapTypeView();
    var promotedType =
        flow
            .propertyGet(
              node,
              isSuperAccess
                  ? SuperPropertyTarget.singleton
                  : ThisPropertyTarget.singleton,
              propertyName,
              member,
              SharedTypeView(memberType),
            )
            ?.unwrapTypeView();
    return new ExpressionTypeAnalysisResult(
      type: SharedTypeView(promotedType ?? memberType),
    );
  }

  ExpressionTypeAnalysisResult analyzeThrow(
    Expression node,
    Expression expression,
  ) {
    analyzeExpression(expression, operations.unknownType);
    flow.handleExit();
    return new ExpressionTypeAnalysisResult(type: operations.neverType);
  }

  void analyzeTryStatement(
    Statement node,
    Statement body,
    Iterable<CatchClause> catchClauses,
    Statement? finallyBlock,
  ) {
    if (finallyBlock != null) {
      flow.tryFinallyStatement_bodyBegin();
    }
    if (catchClauses.isNotEmpty) {
      flow.tryCatchStatement_bodyBegin();
    }
    dispatchStatement(body);
    if (catchClauses.isNotEmpty) {
      flow.tryCatchStatement_bodyEnd(body);
      for (var catch_ in catchClauses) {
        flow.tryCatchStatement_catchBegin(catch_.exception, catch_.stackTrace);
        dispatchStatement(catch_.body);
        flow.tryCatchStatement_catchEnd();
      }
      flow.tryCatchStatement_end();
    }
    if (finallyBlock != null) {
      flow.tryFinallyStatement_finallyBegin(
        catchClauses.isNotEmpty ? node : body,
      );
      dispatchStatement(finallyBlock);
      flow.tryFinallyStatement_end();
    } else {
      handleNoStatement(node);
    }
  }

  ExpressionTypeAnalysisResult analyzeTypeCast(
    Expression node,
    Expression expression,
    Type type,
  ) {
    var subExpressionType = analyzeExpression(
      expression,
      operations.unknownType,
    );
    flow.asExpression_end(
      expression,
      subExpressionType: subExpressionType,
      castType: SharedTypeView(type),
    );
    return new ExpressionTypeAnalysisResult(type: SharedTypeView(type));
  }

  ExpressionTypeAnalysisResult analyzeTypeTest(
    Expression node,
    Expression expression,
    Type type, {
    bool isInverted = false,
  }) {
    var subExpressionType = analyzeExpression(
      expression,
      operations.unknownType,
    );
    flow.isExpression_end(
      node,
      expression,
      isInverted,
      subExpressionType: subExpressionType,
      checkedType: SharedTypeView(type),
    );
    return new ExpressionTypeAnalysisResult(type: operations.boolType);
  }

  ExpressionTypeAnalysisResult analyzeVariableGet(
    Expression node,
    Var variable,
    void Function(Type?)? callback,
  ) {
    var promotedType = flow.variableRead(node, variable);
    callback?.call(promotedType?.unwrapTypeView());
    return new ExpressionTypeAnalysisResult(
      type: promotedType ?? SharedTypeView(variable.type),
    );
  }

  void analyzeWhileLoop(Statement node, Expression condition, Statement body) {
    flow.whileStatement_conditionBegin(node);
    analyzeExpression(condition, operations.unknownType);
    flow.whileStatement_bodyBegin(node, condition);
    _visitLoopBody(node, body);
    flow.whileStatement_end();
  }

  SharedTypeView createNullAwareGuard(
    Expression target,
    SharedTypeView targetType,
  ) {
    var tmp = _harness.irBuilder.allocateTmp(location: target.location);
    startNullShorting(tmp, target, targetType);
    _harness.irBuilder.readTmp(tmp, location: target.location);
    return operations.promoteToNonNull(targetType);
  }

  @override
  void dispatchCollectionElement(
    covariant CollectionElement element,
    covariant CollectionElementContext context,
  ) {
    _irBuilder.guard(element, () => element.visit(_harness, context));
    if (element._expectedIR case var expectedIR?) {
      _irBuilder.check(
        expectedIR,
        Kind.collectionElement,
        location: element.location,
      );
    }
  }

  @override
  ExpressionTypeAnalysisResult dispatchExpression(
    Expression expression,
    SharedTypeSchemaView schema,
  ) {
    if (expression._expectedSchema case var expectedSchema?) {
      expect(schema.unwrapTypeSchemaView<Type>().type, expectedSchema);
    }
    var result = _irBuilder.guard(
      expression,
      () => expression.visit(_harness, schema),
    );
    if (expression._expectedType case var expectedType?) {
      expect(
        result.type.unwrapTypeView<Type>().type,
        expectedType,
        reason: 'at ${expression.location}',
      );
    }
    if (expression._expectedIR case var expectedIR?) {
      _irBuilder.check(
        expectedIR,
        Kind.expression,
        location: expression.location,
      );
    }
    return result;
  }

  @override
  PatternResult dispatchPattern(
    SharedMatchContext context,
    covariant Pattern node,
  ) {
    return node.visit(_harness, context);
  }

  @override
  SharedTypeSchemaView dispatchPatternSchema(covariant Pattern node) {
    return node.computeSchema(_harness);
  }

  @override
  void dispatchStatement(Statement statement) {
    _irBuilder.guard(statement, () => statement.visit(_harness));
    if (statement._expectedIR case var expectedIR?) {
      _irBuilder.check(
        expectedIR,
        Kind.statement,
        location: statement.location,
      );
    }
  }

  @override
  SharedTypeView downwardInferObjectPatternRequiredType({
    required SharedTypeView matchedType,
    required covariant ObjectPattern pattern,
  }) {
    var requiredType = pattern.requiredType;
    if (requiredType.args.isNotEmpty) {
      return SharedTypeView(requiredType);
    } else {
      return SharedTypeView(
        operations.downwardInfer(
          requiredType.name,
          matchedType.unwrapTypeView(),
        ),
      );
    }
  }

  void finish() {
    flow.finish();
  }

  @override
  void finishExpressionCase(Expression node, int caseIndex) {
    _irBuilder.apply(
      'case',
      [Kind.caseHead, Kind.expression],
      Kind.expressionCase,
      location: node.location,
    );
  }

  @override
  void finishJoinedPatternVariable(
    covariant PatternVariableJoin variable, {
    required JoinedPatternVariableLocation location,
    required JoinedPatternVariableInconsistency inconsistency,
    required bool isFinal,
    required SharedTypeView type,
  }) {
    variable.isFinal = isFinal;
    variable.type = type.unwrapTypeView();
    variable.inconsistency = variable.inconsistency.maxWith(inconsistency);
  }

  @override
  shared.MapPatternEntry<Expression, Pattern>? getMapPatternEntry(
    Node element,
  ) {
    if (element is MapPatternEntry) {
      return shared.MapPatternEntry<Expression, Pattern>(
        key: element.key,
        value: element.value,
      );
    }
    return null;
  }

  @override
  Pattern? getRestPatternElementPattern(Node element) {
    return element is RestPattern ? element.subPattern : null;
  }

  @override
  SwitchExpressionMemberInfo<Node, Expression, Var>
  getSwitchExpressionMemberInfo(covariant SwitchExpression node, int index) {
    var case_ = node.cases[index];
    return SwitchExpressionMemberInfo(
      head: CaseHeadOrDefaultInfo(
        pattern: case_.guardedPattern?.pattern,
        variables: case_.guardedPattern?.variables ?? {},
        guard: case_.guardedPattern?.guard,
      ),
      expression: case_.expression,
    );
  }

  @override
  SwitchStatementMemberInfo<Node, Statement, Expression, Var>
  getSwitchStatementMemberInfo(covariant SwitchStatement node, int caseIndex) {
    SwitchStatementMember case_ = node.cases[caseIndex];
    return SwitchStatementMemberInfo(
      heads: [
        for (var element in case_.elements)
          if (element is SwitchHeadCase)
            CaseHeadOrDefaultInfo(
              pattern: element.guardedPattern.pattern,
              variables: element.guardedPattern.variables,
              guard: element.guardedPattern.guard,
            )
          else
            CaseHeadOrDefaultInfo(pattern: null, variables: {}, guard: null),
      ],
      body: case_.body.statements,
      variables: case_._candidateVariables,
      hasLabels: case_.hasLabels,
    );
  }

  @override
  void handle_ifCaseStatement_afterPattern({required covariant IfCase node}) {
    _irVariables(node, node._candidateVariables.values);
  }

  void handleAssignedVariablePattern(covariant VariablePattern node) {
    _irBuilder.atom(node.variable.name, Kind.variable, location: node.location);
    _irBuilder.apply(
      'assignedVarPattern',
      [Kind.variable],
      Kind.pattern,
      location: node.location,
    );
    assert(
      node.expectInferredType == null,
      "assigned variable patterns don't get an inferred type",
    );
  }

  @override
  void handleCase_afterCaseHeads(
    covariant SwitchStatement node,
    int caseIndex,
    Iterable<Var> variables,
  ) {
    var case_ = node.cases[caseIndex];
    _irVariables(node, variables);
    _irBuilder.apply(
      'heads',
      [...List.filled(case_.elements.length, Kind.caseHead), Kind.variables],
      Kind.caseHeads,
      location: node.location,
    );
  }

  @override
  void handleCaseHead(
    Node node, {
    required int caseIndex,
    required int subIndex,
  }) {
    Iterable<Var> variables = [];
    if (node is SwitchExpression) {
      var guardedPattern = node.cases[caseIndex].guardedPattern;
      if (guardedPattern != null) {
        variables = guardedPattern.variables.values;
      }
    } else if (node is SwitchStatement) {
      var head = node.cases[caseIndex].elements[subIndex];
      if (head is SwitchHeadCase) {
        variables = head.guardedPattern.variables.values;
      }
    } else {
      throw UnimplementedError('(${node.runtimeType}) $node');
    }
    _irVariables(node, variables);

    _irBuilder.apply(
      'head',
      [Kind.pattern, Kind.expression, Kind.variables],
      Kind.caseHead,
      location: node.location,
    );
  }

  void handleDeclaredVariablePattern(
    covariant VariablePattern node, {
    required Type matchedType,
    required Type staticType,
  }) {
    _irBuilder.atom(node.variable.name, Kind.variable, location: node.location);
    _irBuilder.atom(matchedType.type, Kind.type, location: node.location);
    _irBuilder.atom(staticType.type, Kind.type, location: node.location);
    _irBuilder.apply(
      'varPattern',
      [Kind.variable, Kind.type, Kind.type],
      Kind.pattern,
      names: ['matchedType', 'staticType'],
      location: node.location,
    );
    var expectInferredType = node.expectInferredType;
    if (expectInferredType != null) {
      expect(
        staticType.type,
        expectInferredType,
        reason: 'at ${node.location}',
      );
    }
  }

  @override
  void handleDefault(
    Node node, {
    required int caseIndex,
    required int subIndex,
  }) {
    _irBuilder.atom('default', Kind.caseHead, location: node.location);
  }

  @override
  void handleListPatternRestElement(
    Pattern container,
    covariant RestPattern restElement,
  ) {
    if (restElement.subPattern != null) {
      _irBuilder.apply(
        '...',
        [Kind.pattern],
        Kind.pattern,
        location: restElement.location,
      );
    } else {
      _irBuilder.atom('...', Kind.pattern, location: restElement.location);
    }
  }

  @override
  void handleMapPatternEntry(
    Pattern container,
    Node entryElement,
    SharedTypeView keyType,
  ) {
    _irBuilder.apply(
      'mapPatternEntry',
      [Kind.expression, Kind.pattern],
      Kind.mapPatternElement,
      location: entryElement.location,
    );
  }

  @override
  void handleMapPatternRestElement(
    Pattern container,
    covariant RestPattern restElement,
  ) {
    if (restElement.subPattern != null) {
      _irBuilder.apply(
        '...',
        [Kind.pattern],
        Kind.mapPatternElement,
        location: restElement.location,
      );
    } else {
      _irBuilder.atom(
        '...',
        Kind.mapPatternElement,
        location: restElement.location,
      );
    }
  }

  @override
  void handleMergedStatementCase(
    covariant SwitchStatement node, {
    required int caseIndex,
    required bool isTerminating,
  }) {
    var numStatements = node.cases[caseIndex].body.statements.length;
    if (!isTerminating) {
      _irBuilder.apply(
        'synthetic-break',
        [],
        Kind.statement,
        location: node.location,
      );
      numStatements++;
    }
    _irBuilder.apply(
      'block',
      List.filled(numStatements, Kind.statement),
      Kind.statement,
      location: node.location,
    );
    _irBuilder.apply(
      'case',
      [Kind.caseHeads, Kind.statement],
      Kind.statementCase,
      location: node.location,
    );
  }

  @override
  void handleNoCollectionElement(Node node) {
    _irBuilder.atom('noop', Kind.collectionElement, location: node.location);
  }

  void handleNoCondition(Node node) {
    _irBuilder.atom('true', Kind.expression, location: node.location);
  }

  @override
  void handleNoGuard(Node node, int caseIndex) {
    _irBuilder.atom('true', Kind.expression, location: node.location);
  }

  void handleNoInitializer(Node node) {
    _irBuilder.atom('uninitialized', Kind.statement, location: node.location);
  }

  void handleNoMessage(Node node) {
    _irBuilder.atom('failure', Kind.expression, location: node.location);
  }

  @override
  void handleNoStatement(Node node) {
    _irBuilder.atom('noop', Kind.statement, location: node.location);
  }

  @override
  void handleNullShortingStep(MiniIRTmp guard, SharedTypeView inferredType) {
    _irBuilder.ifNotNull(guard, location: guard.location);
  }

  @override
  void handleSwitchBeforeAlternative(
    Node node, {
    required int caseIndex,
    required int subIndex,
  }) {}

  @override
  void handleSwitchScrutinee(SharedTypeView type) {}

  @override
  bool isDotShorthand(Node node) {
    return node is DotShorthand;
  }

  @override
  bool isLegacySwitchExhaustive(
    covariant SwitchStatement node,
    SharedTypeView expressionType,
  ) {
    return node.isLegacyExhaustive!;
  }

  @override
  bool isRestPatternElement(Node element) {
    return element is RestPattern;
  }

  @override
  bool isVariablePattern(Node pattern) => pattern is VariablePattern;

  _PropertyElement? lookupInterfaceMember(
    Type receiverType,
    String memberName,
  ) {
    return _harness.getMember(receiverType, memberName);
  }

  @override
  (_PropertyElement?, SharedTypeView) resolveObjectPatternPropertyGet({
    required Pattern objectPattern,
    required SharedTypeView receiverType,
    required shared.RecordPatternField<Node, Pattern> field,
  }) {
    var propertyMember = _harness.getMember(
      receiverType.unwrapTypeView(),
      field.name!,
    );
    return (
      propertyMember,
      SharedTypeView(
        propertyMember?._type ?? operations.dynamicType.unwrapTypeView(),
      ),
    );
  }

  @override
  RelationalOperatorResolution? resolveRelationalPatternOperator(
    covariant RelationalPattern node,
    SharedTypeView matchedValueType,
  ) {
    return _harness.resolveRelationalPatternOperator(
      matchedValueType.unwrapTypeView(),
      node.operator,
    );
  }

  @override
  void setVariableType(Var variable, SharedTypeView type) {
    variable.type = type.unwrapTypeView();
  }

  @override
  String toString() => _irBuilder.toString();

  @override
  SharedTypeView variableTypeFromInitializerType(SharedTypeView type) {
    // Variables whose initializer has type `Null` receive the inferred type
    // `dynamic`.
    if (_harness.operations.classifyType(type) ==
        TypeClassification.nullOrEquivalent) {
      type = operations.dynamicType;
    }
    // Variables whose initializer type includes a promoted type variable
    // receive the nearest supertype that could be expressed in Dart source code
    // (e.g. `T&int` is demoted to `T`).
    // TODO(paulberry): add language tests to verify that the behavior of
    // `type.recursivelyDemote` matches what the analyzer and CFE do.
    return SharedTypeView(
      type.unwrapTypeView<Type>().recursivelyDemote(covariant: true) ??
          type.unwrapTypeView(),
    );
  }

  /// Analyzes the target of a property get or method invocation, looks up the
  /// member being accessed, and returns its type. [propertyGetNode] is the
  /// source representation of the property get itself (or `null` if this is a
  /// method invocation), [target] is the source representation of the target
  /// (or `null` if this is a cascaded access), and [propertyName] is the name
  /// of the property being accessed. [location] is the source location (used
  /// for reporting test failures).
  ///
  /// Returns the type of the member, or a representation of the type `dynamic`
  /// if the member couldn't be found.
  Type _handlePropertyTargetAndMemberLookup(
    Expression? propertyGetNode,
    Expression? target,
    String propertyName, {
    required String location,
    required bool isNullAware,
  }) {
    // Analyze the target, and generate its IR.
    PropertyTarget<Expression> propertyTarget;
    SharedTypeView targetType;
    if (target == null) {
      if (isNullAware) {
        fail(
          "at $location: cascaded accesses shouldn't be marked as null-aware "
          '(the cascade itself should be marked as null-aware instead).',
        );
      }
      // This is a cascaded access so the IR we need to generate is an implicit
      // read of the temporary variable holding the cascade target.
      propertyTarget = CascadePropertyTarget.singleton;
      _harness.irBuilder.readTmp(_currentCascadeTargetIR!, location: location);
      targetType = _currentCascadeTargetType!;
    } else {
      propertyTarget = ExpressionPropertyTarget(target);
      targetType = analyzeExpression(
        target,
        operations.unknownType,
        continueNullShorting: true,
      );
      if (isNullAware) targetType = createNullAwareGuard(target, targetType);
    }
    // Look up the type of the member, applying type promotion if necessary.
    var member = _lookupMember(targetType.unwrapTypeView(), propertyName);
    var memberType =
        member?._type ?? operations.dynamicType.unwrapTypeView<Type>();
    return flow
            .propertyGet(
              propertyGetNode,
              propertyTarget,
              propertyName,
              member,
              SharedTypeView(memberType),
            )
            ?.unwrapTypeView() ??
        memberType;
  }

  void _irVariables(Node node, Iterable<Var> variables) {
    var variableList = variables.toList();
    for (var variable in variableList) {
      _irBuilder.atom(
        variable.stringToCheckVariables,
        Kind.variable,
        location: variable.location,
      );
    }
    _irBuilder.apply(
      'variables',
      List.filled(variableList.length, Kind.variable),
      Kind.variables,
      location: node.location,
    );
  }

  _PropertyElement? _lookupMember(Type receiverType, String memberName) {
    return lookupInterfaceMember(receiverType, memberName);
  }

  void _visitLoopBody(Statement loop, Statement body) {
    var previousBreakTarget = _currentBreakTarget;
    var previousContinueTarget = _currentContinueTarget;
    _currentBreakTarget = loop;
    _currentContinueTarget = loop;
    dispatchStatement(body);
    _currentBreakTarget = previousBreakTarget;
    _currentContinueTarget = previousContinueTarget;
  }
}

/// Mini-ast representation of a class property.  Instances of this class are
/// used to represent class members in the flow analysis `promotableFields` set.
class _PropertyElement {
  /// The type of the property.
  final Type _type;

  /// The name of the property (used by toString)
  final String _name;

  /// Whether the property is promotable.
  final bool isPromotable;

  /// The reason the property is not promotable, if applicable and relevant to
  /// the test.
  ///
  /// If the propery is promotable ([isPromotable] is `true`), this value is
  /// always `null`.
  ///
  /// Otherwise the value *may* be a reason for the property not being
  /// promotable, but it may also still be `null` if the reason is not relevant
  /// to the test.
  final PropertyNonPromotabilityReason? whyNotPromotable;

  _PropertyElement(
    this._type,
    this._name, {
    required this.isPromotable,
    required this.whyNotPromotable,
  }) {
    if (isPromotable) {
      assert(whyNotPromotable == null);
    }
  }

  @override
  String toString() => '$_type.$_name';
}

class _VariableBinder extends VariableBinder<Node, Var> {
  final PreVisitor visitor;

  _VariableBinder(this.visitor) : super(errors: visitor.errors);

  @override
  Var joinPatternVariables({
    required Object? key,
    required List<Var> components,
    required JoinedPatternVariableInconsistency inconsistency,
  }) {
    var joinedVariable = components[0]._joinedVar;
    if (joinedVariable == null) {
      fail('No joined variable for ${components[0].location}');
    }
    joinedVariable._handleJoin(
      components: components,
      inconsistency: inconsistency,
      visitor: visitor,
    );
    return joinedVariable;
  }
}
