// 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 Declare._(
    new VariablePattern._(
      type == null ? null : Type(type),
      variable,
      expectInferredType,
      location: location,
    ),
    initializer?.asExpression(location: location),
    isLate: isLate,
    isFinal: isFinal,
    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,
  );
}

Statement match(
  Pattern pattern,
  ProtoExpression initializer, {
  bool isLate = false,
  bool isFinal = false,
}) {
  var location = computeLocation();
  return new Declare._(
    pattern,
    initializer.asExpression(location: location),
    isLate: isLate,
    isFinal: isFinal,
    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,
  );
}

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 Declare extends Statement {
  final bool isLate;
  final bool isFinal;
  final Pattern pattern;
  final Expression? initializer;

  Declare._(
    this.pattern,
    this.initializer, {
    required this.isLate,
    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();
    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',
      pattern._debugString(needsKeywordOrType: !isFinal),
      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;
    if (isLate) {
      // Late declarations are not allowed using patterns, so interpret the
      // declaration as an old-fashioned variable declaration.
      var pattern = this.pattern as VariablePattern;
      var variable = pattern.variable;
      h.irBuilder.atom(variable.name, Kind.variable, location: location);
      var declaredType = pattern.declaredType;
      Type staticType;
      if (initializer == null) {
        // Use the shared logic for analyzing uninitialized variable
        // declarations.
        staticType =
            h.typeAnalyzer
                .analyzeUninitializedVariableDeclaration(
                  this,
                  pattern.variable,
                  declaredType?.wrapSharedTypeView(),
                  isFinal: isFinal,
                )
                .unwrapTypeView();
        irName = 'declare';
        argKinds = [Kind.variable];
      } else {
        // There's no shared logic for analyzing initialized late variable
        // declarations, so analyze the declaration directly.
        h.flow.lateInitializer_begin(this);
        var initializerType =
            h.typeAnalyzer
                .analyzeExpression(
                  initializer,
                  declaredType?.wrapSharedTypeSchemaView() ??
                      h.operations.unknownType,
                )
                .unwrapTypeView<Type>();
        h.flow.lateInitializer_end();
        staticType = variable.type = declaredType ?? initializerType;
        h.flow.declare(variable, SharedTypeView(staticType), initialized: true);
        h.flow.initialize(
          variable,
          SharedTypeView(initializerType),
          initializer,
          isFinal: isFinal,
          isLate: true,
          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 = pattern.expectInferredType;
      if (expectInferredType != null) {
        expect(staticType, expectInferredType);
      }
    } else if (initializer == null) {
      var pattern = this.pattern as VariablePattern;
      var declaredType = pattern.declaredType;
      var staticType =
          h.typeAnalyzer
              .analyzeUninitializedVariableDeclaration(
                this,
                pattern.variable,
                declaredType?.wrapSharedTypeView(),
                isFinal: isFinal,
              )
              .unwrapTypeView<Type>();
      h.typeAnalyzer.handleDeclaredVariablePattern(
        pattern,
        matchedType: staticType,
        staticType: staticType,
      );
      irName = 'declare';
      argKinds = [Kind.pattern];
    } else {
      h.typeAnalyzer.analyzePatternVariableDeclaration(
        this,
        pattern,
        initializer,
        isFinal: isFinal,
      );
      irName = 'match';
      argKinds = [Kind.expression, Kind.pattern];
    }
    h.irBuilder.apply(
      [irName, if (isLate) 'late', if (isFinal) 'final'].join('_'),
      argKinds,
      Kind.statement,
      location: location,
      names: names,
    );
  }
}

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

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