// Copyright (c) 2023, 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.

part of '../../ast.dart';

sealed class Pattern extends TreeNode {
  /// Variable declarations induced by nested variable patterns.
  ///
  /// These variables are initialized to the values captured by the variable
  /// patterns nested in the pattern.
  List<DeclaredVariable> get declaredVariables;

  @override
  R accept<R>(PatternVisitor<R> visitor);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg);

  /// Returns the variable name that this pattern defines, if any.
  ///
  /// This is used to derive an implicit variable name from a pattern to use
  /// on object patterns. For instance
  ///
  ///    if (o case Foo(:var bar, :var baz!)) { ... }
  ///
  /// the getter names 'bar' and 'baz' are implicitly defined by the patterns.
  String? get variableName => null;
}

/// A [Pattern] based on a constant [Expression].
class ConstantPattern extends Pattern {
  Expression expression;

  /// Static type of the expression as computed during inference.
  DartType? expressionType;

  /// Reference to the `operator ==` procedure on [expression].
  ///
  /// This is set during inference.
  Reference? equalsTargetReference;

  /// The type of the `operator ==` procedure on [expression].
  ///
  /// This is set during inference.
  FunctionType? equalsType;

  /// The [Constant] value for this constant pattern.
  ///
  /// This is set during constant evaluation.
  Constant? value;

  new(this.expression) {
    expression.parent = this;
  }

  /// The `operator ==` procedure on [expression].
  ///
  /// This is set during inference.
  Procedure get equalsTarget => equalsTargetReference!.asProcedure;

  void set equalsTarget(Procedure value) {
    equalsTargetReference = value.reference;
  }

  @override
  List<DeclaredVariable> get declaredVariables => const [];

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitConstantPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitConstantPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    expression = v.transform(expression)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    expression = v.transform(expression)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    expression.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    expression.toTextInternal(printer);
  }

  @override
  String toString() {
    return "ConstantPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `pattern && pattern`.
class AndPattern extends Pattern {
  Pattern left;
  Pattern right;

  @override
  List<DeclaredVariable> get declaredVariables => [
    ...left.declaredVariables,
    ...right.declaredVariables,
  ];

  new(this.left, this.right) {
    left.parent = this;
    right.parent = this;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitAndPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitAndPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    left = v.transform(left)..parent = this;
    right = v.transform(right)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    left = v.transform(left)..parent = this;
    right = v.transform(right)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    left.accept(v);
    right.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    left.toTextInternal(printer);
    printer.write(' && ');
    right.toTextInternal(printer);
  }

  @override
  String toString() {
    return "AndPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `pattern || pattern`.
class OrPattern extends Pattern {
  Pattern left;
  Pattern right;

  final List<DeclaredVariable> orPatternJointVariables;

  @override
  List<DeclaredVariable> get declaredVariables => orPatternJointVariables;

  new(
    this.left,
    this.right, {
    required List<DeclaredVariable> orPatternJointVariables,
  }) : orPatternJointVariables = orPatternJointVariables {
    left.parent = this;
    right.parent = this;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitOrPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitOrPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    left = v.transform(left)..parent = this;
    right = v.transform(right)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    left = v.transform(left)..parent = this;
    right = v.transform(right)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    left.accept(v);
    right.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    left.toTextInternal(printer);
    printer.write(' || ');
    right.toTextInternal(printer);
  }

  @override
  String toString() {
    return "OrPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `pattern as type`.
class CastPattern extends Pattern {
  Pattern pattern;
  DartType type;

  new(this.pattern, this.type) {
    pattern.parent = this;
  }

  @override
  String? get variableName => pattern.variableName;

  @override
  List<DeclaredVariable> get declaredVariables => pattern.declaredVariables;

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitCastPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitCastPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
    type = v.visitDartType(type);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
    type = v.visitDartType(type, cannotRemoveSentinel);
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
    type.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    pattern.toTextInternal(printer);
    printer.write(' as ');
    printer.writeType(type);
  }

  @override
  String toString() {
    return "CastPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `pattern!`.
class NullAssertPattern extends Pattern {
  Pattern pattern;

  new(this.pattern) {
    pattern.parent = this;
  }

  @override
  String? get variableName => pattern.variableName;

  @override
  List<DeclaredVariable> get declaredVariables => pattern.declaredVariables;

  @override
  R accept<R>(PatternVisitor<R> visitor) =>
      visitor.visitNullAssertPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitNullAssertPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    pattern.toTextInternal(printer);
    printer.write('!');
  }

  @override
  String toString() {
    return "NullAssertPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `pattern?`.
class NullCheckPattern extends Pattern {
  Pattern pattern;

  new(this.pattern) {
    pattern.parent = this;
  }

  @override
  String? get variableName => pattern.variableName;

  @override
  List<DeclaredVariable> get declaredVariables => pattern.declaredVariables;

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitNullCheckPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitNullCheckPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    pattern.toTextInternal(printer);
    printer.write('?');
  }

  @override
  String toString() {
    return "NullCheckPattern(${toStringInternal()})";
  }
}

/// A [Pattern] for `<typeArgument>[pattern0, ... patternN]`.
class ListPattern extends Pattern {
  static const int FlagNeedsCheck = 1 << 0;
  static const int FlagHasRestPattern = 1 << 1;

  int flags = 0;

  /// The element type argument as specified by the list pattern syntax.
  DartType? typeArgument;

  List<Pattern> patterns;

  /// The required type of the pattern.
  ///
  /// This is the type the matched expression is checked against, if the
  /// [matchedValueType] is not already a subtype of [requiredType].
  ///
  /// This is set during inference.
  DartType? requiredType;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// If `true`, the matched expression must be checked to be a `List`.
  ///
  /// This is set during inference.
  bool get needsCheck => flags & FlagNeedsCheck != 0;
  void set needsCheck(bool value) {
    flags = value ? (flags | FlagNeedsCheck) : (flags & ~FlagNeedsCheck);
  }

  /// The most specific type of the matched expression. Either the
  /// [requiredType] or the [matchedValueType] if it is a subtype of
  /// [requiredType].
  ///
  /// This is the type on which pattern accesses from [patterns] are looked up.
  ///
  /// This is set during inference.
  DartType? lookupType;

  /// If `true`, this list pattern contains a rest pattern.
  ///
  /// This is set during inference.
  bool get hasRestPattern => flags & FlagHasRestPattern != 0;
  void set hasRestPattern(bool value) {
    flags = value
        ? (flags | FlagHasRestPattern)
        : (flags & ~FlagHasRestPattern);
  }

  /// Reference to the target of the `length` property of the list.
  ///
  /// This is set during inference.
  Reference? lengthTargetReference;

  /// The type of the `length` property of the list.
  ///
  /// This is set during inference.
  DartType? lengthType;

  /// Reference to the method used to check the `length` of the list.
  ///
  /// If this pattern has a rest pattern, this is an `operator >=` method.
  /// Otherwise this is an `operator ==` method.
  ///
  /// This is set during inference.
  Reference? lengthCheckTargetReference;

  /// The type of the method used to check the `length` of the list.
  ///
  /// If this pattern has a rest pattern, this is an `operator >=` method.
  /// Otherwise this is an `operator ==` method.
  ///
  /// This is set during inference.
  FunctionType? lengthCheckType;

  /// Reference to the target of the `sublist` method of the list.
  ///
  /// This is used if this pattern has a rest pattern with a subpattern.
  ///
  /// This is set during inference.
  Reference? sublistTargetReference;

  /// The type of the `sublist` method of the list.
  ///
  /// This is used if this pattern has a rest pattern with a subpattern.
  ///
  /// This is set during inference.
  FunctionType? sublistType;

  /// Reference to the target of the `minus` method of the `length` of this
  /// list.
  ///
  /// This is used to compute tail indices if this pattern has a rest pattern.
  ///
  /// This is set during inference.
  Reference? minusTargetReference;

  /// The type of the `minus` method of the `length` of this list.
  ///
  /// This is used to compute tail indices if this pattern has a rest pattern.
  ///
  /// This is set during inference.
  FunctionType? minusType;

  /// Reference to the target of the `operator []` method of the list.
  ///
  /// This is set during inference.
  Reference? indexGetTargetReference;

  /// The type of the `operator []` method of the list.
  ///
  /// This is set during inference.
  FunctionType? indexGetType;

  @override
  List<DeclaredVariable> get declaredVariables => [
    for (Pattern pattern in patterns) ...pattern.declaredVariables,
  ];

  new(this.typeArgument, this.patterns) {
    setParents(patterns, this);
  }

  /// The target of the `length` property of the list.
  ///
  /// This is set during inference.
  Member get lengthTarget => lengthTargetReference!.asMember;

  void set lengthTarget(Member value) {
    lengthTargetReference = value.reference;
  }

  /// The method used to check the `length` of the list.
  ///
  /// If this pattern has a rest pattern, this is an `operator >=` method. If
  /// this is the empty list pattern, this an `operator <=` method. Otherwise
  /// this is an `operator ==` method.
  ///
  /// This is set during inference.
  Procedure get lengthCheckTarget => lengthCheckTargetReference!.asProcedure;

  void set lengthCheckTarget(Procedure value) {
    lengthCheckTargetReference = value.reference;
  }

  /// The target of the `sublist` method of the list.
  ///
  /// This is used if this pattern has a rest pattern with a subpattern.
  ///
  /// This is set during inference.
  Procedure get sublistTarget => sublistTargetReference!.asProcedure;

  void set sublistTarget(Procedure value) {
    sublistTargetReference = value.reference;
  }

  /// The target of the `minus` method of the `length` of this list.
  ///
  /// This is used to compute tail indices if this pattern has a rest pattern.
  ///
  /// This is set during inference.
  Procedure get minusTarget => minusTargetReference!.asProcedure;

  void set minusTarget(Procedure value) {
    minusTargetReference = value.reference;
  }

  /// The target of the `operator []` method of the list.
  ///
  /// This is set during inference.
  Procedure get indexGetTarget => indexGetTargetReference!.asProcedure;

  void set indexGetTarget(Procedure value) {
    indexGetTargetReference = value.reference;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitListPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitListPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    if (typeArgument != null) {
      typeArgument = v.visitDartType(typeArgument!);
    }
    v.transformList(patterns, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    if (typeArgument != null) {
      DartType newTypeArgument = v.visitDartType(typeArgument!, dummyDartType);
      if (identical(newTypeArgument, dummyDartType)) {
        typeArgument = null;
      } else {
        typeArgument = newTypeArgument;
      }
    }
    v.transformList(patterns, this, dummyPattern);
  }

  @override
  void visitChildren(Visitor v) {
    typeArgument?.accept(v);
    visitList(patterns, v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    if (typeArgument != null) {
      printer.write('<');
      printer.writeType(typeArgument!);
      printer.write('>');
    }
    printer.write('[');
    String comma = '';
    for (Pattern pattern in patterns) {
      printer.write(comma);
      pattern.toTextInternal(printer);
      comma = ', ';
    }
    printer.write(']');
  }

  @override
  String toString() {
    return "ListPattern(${toStringInternal()})";
  }
}

class ObjectPattern extends Pattern {
  /// The type specified as part of the object pattern syntax.
  ///
  /// This is the type the matched expression is checked against, if the
  /// [matchedValueType] is not already a subtype of [requiredType].
  ///
  /// This is the type on which pattern accesses from [fields] are looked up.
  ///
  /// This is set during inference.
  DartType requiredType;

  final List<NamedPattern> fields;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// If `true`, the matched expression must be checked to be of type
  /// [requiredType].
  ///
  /// This is set during inference.
  bool needsCheck = false;

  /// The most specific type of the matched expression. Either the
  /// [requiredType] or the [matchedValueType] if it is a subtype of
  /// [requiredType].
  ///
  /// This is set during inference.
  // TODO(johnniwinther): Remove this field. It is no longer used.
  DartType? lookupType;

  new(this.requiredType, this.fields) {
    setParents(fields, this);
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitObjectPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitObjectPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    requiredType = v.visitDartType(requiredType);
    v.transformList(fields, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    requiredType = v.visitDartType(requiredType, cannotRemoveSentinel);
    v.transformList(fields, this, dummyNamedPattern);
  }

  @override
  void visitChildren(Visitor v) {
    requiredType.accept(v);
    visitList(fields, v);
  }

  @override
  List<DeclaredVariable> get declaredVariables {
    return [for (NamedPattern field in fields) ...field.declaredVariables];
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.writeType(requiredType);
    printer.write('(');
    String comma = '';
    for (Pattern field in fields) {
      printer.write(comma);
      field.toTextInternal(printer);
      comma = ', ';
    }
    printer.write(')');
  }

  @override
  String toString() {
    return "ObjectPattern(${toStringInternal()})";
  }
}

enum RelationalPatternKind {
  equals,
  notEquals,
  lessThan,
  lessThanEqual,
  greaterThan,
  greaterThanEqual,
}

/// A [Pattern] for `operator expression` where `operator  is either ==, !=,
/// <, <=, >, or >=.
class RelationalPattern extends Pattern {
  final RelationalPatternKind kind;
  Expression expression;

  /// The type of the [expression].
  ///
  /// This is set during inference.
  DartType? expressionType;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// The access kind for performing the relational operation of this pattern.
  ///
  /// This is set during inference.
  RelationalAccessKind accessKind = RelationalAccessKind.Invalid;

  /// The name of the relational operation called by this pattern.
  ///
  /// This is set during inference.
  Name? name;

  /// Reference to the target [Procedure] called by this pattern.
  ///
  /// This is used for [RelationalAccessKind.Instance] and
  /// [RelationalAccessKind.Static].
  ///
  /// This is set during inference.
  Reference? targetReference;

  /// The type arguments passed to [target].
  ///
  /// This is used for [RelationalAccessKind.Static].
  ///
  /// This is set during inference.
  List<DartType>? typeArguments;

  /// The type of [target].
  ///
  /// This is used for [RelationalAccessKind.Instance] and
  /// [RelationalAccessKind.Static].
  ///
  /// This is set during inference.
  FunctionType? functionType;

  /// The [Constant] value for the [expression].
  ///
  /// This is set during constant evaluation.
  Constant? expressionValue;

  new(this.kind, this.expression) {
    expression.parent = this;
  }

  /// The target [Procedure] called by this pattern.
  ///
  /// This is used for [RelationalAccessKind.Instance] and
  /// [RelationalAccessKind.Static].
  ///
  /// This is set during inference.
  Procedure? get target => targetReference?.asProcedure;

  void set target(Procedure? value) {
    targetReference = value?.reference;
  }

  @override
  List<DeclaredVariable> get declaredVariables => const [];

  @override
  R accept<R>(PatternVisitor<R> visitor) =>
      visitor.visitRelationalPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitRelationalPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    expression = v.transform(expression)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    expression = v.transform(expression)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    expression.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    switch (kind) {
      case RelationalPatternKind.equals:
        printer.write('== ');
        break;
      case RelationalPatternKind.notEquals:
        printer.write('!= ');
        break;
      case RelationalPatternKind.lessThan:
        printer.write('< ');
        break;
      case RelationalPatternKind.lessThanEqual:
        printer.write('<= ');
        break;
      case RelationalPatternKind.greaterThan:
        printer.write('> ');
        break;
      case RelationalPatternKind.greaterThanEqual:
        printer.write('>= ');
        break;
    }
    printer.writeExpression(expression);
  }

  @override
  String toString() {
    return "RelationalPattern(${toStringInternal()})";
  }
}

class WildcardPattern extends Pattern {
  DartType? type;

  new(this.type);

  @override
  List<DeclaredVariable> get declaredVariables => const [];

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitWildcardPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitWildcardPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    if (type != null) {
      type = v.visitDartType(type!);
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    if (type != null) {
      DartType newType = v.visitDartType(type!, dummyDartType);
      if (identical(newType, dummyDartType)) {
        type = null;
      } else {
        type = newType;
      }
    }
  }

  @override
  void visitChildren(Visitor v) {
    type?.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    if (type != null) {
      type!.toTextInternal(printer);
      printer.write(" ");
    }
    printer.write("_");
  }

  @override
  String toString() {
    return "WildcardPattern(${toStringInternal()})";
  }
}

class AssignedVariablePattern extends Pattern {
  final Variable variable;

  /// If [variable] is a lowered late variable, [setter] holds the variable of
  /// the local function that should be used for assignment.
  Variable? setter;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// If `true`, the matched expression must be checked to be of the type
  /// of [variable].
  ///
  /// This is set during inference.
  bool needsCast = false;

  /// If `true`, the assignment occurs in a context where effects can be
  /// observed and must therefore be postponed until the whole pattern has been
  /// evaluated.
  ///
  /// This is used an optimized encoding of pattern assignment. It is sound to
  /// assume that all [AssignedVariablePattern]s have an observable effect.
  ///
  /// For instance
  ///
  ///     class A {
  ///       get b => throw 'foo';
  ///     }
  ///     class B extends A {
  ///       get b => 42;
  ///     }
  ///     method(A a) {
  ///       var b1;
  ///       var b2;
  ///       A(b: b1) = a;
  ///       try {
  ///         A(b: b2) = a;
  ///       } catch (_) {
  ///       }
  ///       print(b1);
  ///       print(b2);
  ///     }
  ///
  /// Here the assignment to `b2` has an observable effect where as `b1` has
  /// not.
  bool hasObservableEffect = true;

  new(this.variable);

  @override
  R accept<R>(PatternVisitor<R> visitor) =>
      visitor.visitAssignedVariablePattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitAssignedVariablePattern(this, arg);

  @override
  void transformChildren(Transformer v) {}

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {}

  @override
  void visitChildren(Visitor v) {}

  @override
  List<DeclaredVariable> get declaredVariables => const [];

  @override
  String? get variableName => variable.cosmeticName!;

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write(variable.cosmeticName!);
  }

  @override
  String toString() {
    return "AssignedVariablePattern(${toStringInternal()})";
  }
}

class MapPattern extends Pattern {
  static const int FlagNeedsCheck = 1 << 0;

  int flags = 0;

  /// The key type arguments as specific in the map pattern syntax.
  DartType? keyType;

  /// The value type arguments as specific in the map pattern syntax.
  DartType? valueType;

  final List<MapPatternEntry> entries;

  /// The required type of the pattern.
  ///
  /// This is the type the matched expression is checked against, if the
  /// [matchedValueType] is not already a subtype of [requiredType].
  ///
  /// This is set during inference.
  DartType? requiredType;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// If `true`, the matched expression must be checked to be a `Map`.
  ///
  /// This is set during inference.
  bool get needsCheck => flags & FlagNeedsCheck != 0;
  void set needsCheck(bool value) {
    flags = value ? (flags | FlagNeedsCheck) : (flags & ~FlagNeedsCheck);
  }

  /// The most specific type of the matched expression. Either the
  /// [requiredType] or the [matchedValueType] if it is a subtype of
  /// [requiredType].
  ///
  /// This is the type on which pattern accesses from [entries] are looked up.
  ///
  /// This is set during inference.
  DartType? lookupType;

  /// Reference to the target of the `containsKey` method of the map.
  ///
  /// This is set during inference.
  Reference? containsKeyTargetReference;

  /// The type of the `containsKey` method of the map.
  ///
  /// This is set during inference.
  FunctionType? containsKeyType;

  /// Reference to the target of the `operator []` method of the map.
  ///
  /// This is set during inference.
  Reference? indexGetTargetReference;

  /// The type of the `operator []` method of the map.
  ///
  /// This is set during inference.
  FunctionType? indexGetType;

  @override
  List<DeclaredVariable> get declaredVariables => [
    for (MapPatternEntry entry in entries)
      if (entry is! MapPatternRestEntry) ...entry.value.declaredVariables,
  ];

  new(this.keyType, this.valueType, this.entries)
    : assert((keyType == null) == (valueType == null)) {
    setParents(entries, this);
  }

  /// The target of the `containsKey` method of the map.
  ///
  /// This is set during inference.
  Procedure get containsKeyTarget => containsKeyTargetReference!.asProcedure;

  void set containsKeyTarget(Procedure value) {
    containsKeyTargetReference = value.reference;
  }

  /// The target of the `operator []` method of the map.
  ///
  /// This is set during inference.
  Procedure get indexGetTarget => indexGetTargetReference!.asProcedure;
  void set indexGetTarget(Procedure value) {
    indexGetTargetReference = value.reference;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitMapPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitMapPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    if (keyType != null) {
      keyType = v.visitDartType(keyType!);
    }
    if (valueType != null) {
      valueType = v.visitDartType(valueType!);
    }
    v.transformList(entries, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    if (keyType != null) {
      DartType newType = v.visitDartType(keyType!, dummyDartType);
      if (identical(newType, dummyDartType)) {
        keyType = null;
      } else {
        keyType = newType;
      }
    }
    if (valueType != null) {
      DartType newType = v.visitDartType(valueType!, dummyDartType);
      if (identical(newType, dummyDartType)) {
        valueType = null;
      } else {
        valueType = newType;
      }
    }
    v.transformList(entries, this, dummyMapPatternEntry);
  }

  @override
  void visitChildren(Visitor v) {
    keyType?.accept(v);
    valueType?.accept(v);
    visitList(entries, v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    if (keyType != null && valueType != null) {
      printer.writeTypeArguments([keyType!, valueType!]);
    }
    printer.write('{');
    String comma = '';
    for (MapPatternEntry entry in entries) {
      printer.write(comma);
      entry.toTextInternal(printer);
      comma = ', ';
    }
    printer.write('}');
  }

  @override
  String toString() {
    return 'MapPattern(${toStringInternal()})';
  }
}

class NamedPattern extends Pattern {
  final String name;
  Pattern pattern;

  /// When used in an object pattern, this holds the named of the property
  /// accessed by this pattern.
  ///
  /// This is set during inference.
  Name fieldName = new Name('#');

  /// When used in an object pattern, this holds the access kind of used for
  /// reading the property value for this pattern.
  ///
  /// This is set during inference.
  ObjectAccessKind accessKind = ObjectAccessKind.Invalid;

  /// When used in an object pattern, this holds the reference to the target
  /// [Member] used to read the property for this pattern.
  ///
  /// This is used for [ObjectAccessKind.Object], [ObjectAccessKind.Instance],
  /// and [ObjectAccessKind.Static].
  ///
  /// This is set during inference.
  Reference? targetReference;

  /// When used in an object pattern, this holds the static property type for
  /// this pattern.
  ///
  /// This is used for [ObjectAccessKind.Object], [ObjectAccessKind.Instance],
  /// and [ObjectAccessKind.Static].
  ///
  /// This is set during inference.
  DartType? resultType;

  /// When used in an object pattern, this is set to `true` if the field value
  /// needs to be checked against the [resultType]. This is needed for fields
  /// whose type contain covariant types that occur in non-covariant positions.
  bool checkReturn = false;

  /// When used in an object pattern, this holds the record on which the
  /// property for this pattern is read.
  ///
  /// This is used for [ObjectAccessKind.RecordNamed] and
  /// [ObjectAccessKind.RecordIndexed].
  ///
  /// This is set during inference.
  RecordType? recordType;

  /// When used in an object pattern, this holds the record field index from
  /// which the property for this pattern is read.
  ///
  /// This is used for [ObjectAccessKind.RecordIndexed].
  ///
  /// This is set during inference.
  int recordFieldIndex = -1;

  /// When used in an object pattern, this holds the function type of [target]
  /// called to read the property for this pattern.
  ///
  /// This is set during inference.
  // TODO(johnniwinther): Remove this. This is no longer used.
  FunctionType? functionType;

  /// When used in an object pattern, this holds the type arguments used when
  /// called the [target] to read the property for this pattern.
  ///
  /// This is used for [ObjectAccessKind.Static].
  ///
  /// This is set during inference.
  List<DartType>? typeArguments;

  @override
  List<DeclaredVariable> get declaredVariables => pattern.declaredVariables;

  new(this.name, this.pattern) {
    pattern.parent = this;
  }

  /// When used in an object pattern, this holds the target [Member] used to
  /// read the property for this pattern.
  ///
  /// This is used for [ObjectAccessKind.Object], [ObjectAccessKind.Instance],
  /// and [ObjectAccessKind.Static].
  ///
  /// This is set during inference.
  Member? get target => targetReference?.asMember;

  void set target(Member? value) {
    targetReference = value?.reference;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitNamedPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitNamedPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write(name);
    printer.write(': ');
    pattern.toTextInternal(printer);
  }

  @override
  String toString() {
    return 'NamedPattern(${toStringInternal()})';
  }
}

class RecordPattern extends Pattern {
  final List<Pattern> patterns;

  /// The required type of the pattern.
  ///
  /// This is the type the matched expression is checked against, if the
  /// [matchedValueType] is not already a subtype of [requiredType].
  ///
  /// This is set during inference.
  RecordType? requiredType;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  /// If `true`, the matched expression must be checked to be of type
  /// [requiredType].
  ///
  /// This is set during inference.
  bool needsCheck = false;

  /// The most specific type of the matched expression. Either the
  /// [requiredType] or the [matchedValueType] if it is a subtype of
  /// [requiredType].
  ///
  /// This is the type on which pattern accesses from [patterns] are looked up.
  ///
  /// This is set during inference.
  RecordType? lookupType;

  @override
  List<DeclaredVariable> get declaredVariables => [
    for (Pattern pattern in patterns) ...pattern.declaredVariables,
  ];

  new(this.patterns) {
    setParents(patterns, this);
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitRecordPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitRecordPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    v.transformList(patterns, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    v.transformList(patterns, this, dummyPattern);
  }

  @override
  void visitChildren(Visitor v) {
    visitList(patterns, v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('(');
    String comma = '';
    for (Pattern pattern in patterns) {
      printer.write(comma);
      pattern.toTextInternal(printer);
      comma = ', ';
    }
    printer.write(')');
  }

  @override
  String toString() {
    return 'RecordPattern(${toStringInternal()})';
  }
}

class VariablePattern extends Pattern {
  // TODO(johnniwinther): Should this be accessed through [variable] instead?
  DartType? type;
  DeclaredVariable variable;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  @override
  List<DeclaredVariable> get declaredVariables => [variable];

  new(this.type, this.variable) {
    variable.parent = this;
  }

  @override
  String? get variableName => variable.cosmeticName;

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitVariablePattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitVariablePattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    if (type != null) {
      type = v.visitDartType(type!);
    }
    variable = v.transform(variable)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    if (type != null) {
      DartType newType = v.visitDartType(type!, dummyDartType);
      if (identical(newType, dummyDartType)) {
        type = null;
      } else {
        type = newType;
      }
    }
    variable = v.transform(variable)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    type?.accept(v);
    variable.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    if (type != null) {
      type!.toTextInternal(printer);
      printer.write(" ");
    } else {
      printer.write("var ");
    }
    printer.write(variable.cosmeticName!);
  }

  @override
  String toString() {
    return "VariablePattern(${toStringInternal()})";
  }
}

class RestPattern extends Pattern {
  Pattern? subPattern;

  new(this.subPattern) {
    subPattern?.parent = this;
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitRestPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitRestPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    if (subPattern != null) {
      subPattern = v.transform(subPattern!)..parent = this;
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    if (subPattern != null) {
      subPattern = v.transform(subPattern!)..parent = this;
    }
  }

  @override
  void visitChildren(Visitor v) {
    subPattern?.accept(v);
  }

  @override
  List<DeclaredVariable> get declaredVariables =>
      subPattern?.declaredVariables ?? const [];

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('...');
    if (subPattern != null) {
      subPattern!.toTextInternal(printer);
    }
  }

  @override
  String toString() {
    return "RestPattern(${toStringInternal()})";
  }
}

class InvalidPattern extends Pattern {
  Expression invalidExpression;

  @override
  final List<DeclaredVariable> declaredVariables;

  new(this.invalidExpression, {required this.declaredVariables}) {
    invalidExpression.parent = this;
    setParents(declaredVariables, this);
  }

  @override
  R accept<R>(PatternVisitor<R> visitor) => visitor.visitInvalidPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> visitor, A arg) =>
      visitor.visitInvalidPattern(this, arg);

  @override
  void transformChildren(Transformer v) {
    invalidExpression = v.transform(invalidExpression)..parent = this;
    v.transformList(declaredVariables, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    invalidExpression = v.transform(invalidExpression)..parent = this;
    v.transformVariableList(declaredVariables, this);
  }

  @override
  void visitChildren(Visitor v) {
    invalidExpression.accept(v);
    visitList(declaredVariables, v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.writeExpression(invalidExpression);
  }

  @override
  String toString() {
    return "InvalidPattern(${toStringInternal()})";
  }
}

/// Abstract subclass of [Pattern] that can be used to add [Pattern]
/// subclasses from outside `package:kernel`.
abstract class AuxiliaryPattern extends Pattern {
  @override
  R accept<R>(PatternVisitor<R> v) => v.visitAuxiliaryPattern(this);

  @override
  R accept1<R, A>(PatternVisitor1<R, A> v, A arg) =>
      v.visitAuxiliaryPattern(this, arg);
}

class MapPatternEntry extends TreeNode {
  Expression key;
  Pattern value;

  DartType? keyType;

  /// The [Constant] value for the [key] expression.
  ///
  /// This is set during constant evaluation.
  Constant? keyValue;

  new(this.key, this.value) {
    key.parent = this;
    value.parent = this;
  }

  @override
  R accept<R>(TreeVisitor<R> v) {
    return v.visitMapPatternEntry(this);
  }

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
    return v.visitMapPatternEntry(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    key = v.transform(key)..parent = this;
    if (keyType != null) {
      keyType = v.visitDartType(keyType!);
    }
    value = v.transform(value)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    key = v.transform(key)..parent = this;
    if (keyType != null) {
      keyType = v.visitDartType(keyType!, cannotRemoveSentinel);
    }
    value = v.transform(value)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    key.accept(v);
    keyType?.accept(v);
    value.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    key.toTextInternal(printer);
    printer.write(': ');
    value.toTextInternal(printer);
  }

  @override
  String toString() {
    return 'MapPatternEntry(${toStringInternal()})';
  }
}

class MapPatternRestEntry extends TreeNode implements MapPatternEntry {
  new();

  @override
  Expression get key => throw new UnsupportedError('MapPatternRestEntry.key');

  @override
  void set key(Expression value) =>
      throw new UnsupportedError('MapPatternRestEntry.key=');

  @override
  DartType? get keyType =>
      throw new UnsupportedError('MapPatternRestEntry.keyType');

  @override
  void set keyType(DartType? value) =>
      throw new UnsupportedError('MapPatternRestEntry.keyType=');

  @override
  Pattern get value => throw new UnsupportedError('MapPatternRestEntry.value');

  @override
  void set value(Pattern value) =>
      throw new UnsupportedError('MapPatternRestEntry.value=');

  @override
  Constant? get keyValue =>
      throw new UnsupportedError('MapPatternRestEntry.keyValue');

  @override
  void set keyValue(Constant? value) =>
      throw new UnsupportedError('MapPatternRestEntry.keyValue=');

  @override
  R accept<R>(TreeVisitor<R> v) {
    return v.visitMapPatternRestEntry(this);
  }

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
    return v.visitMapPatternRestEntry(this, arg);
  }

  @override
  void transformChildren(Transformer v) {}

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {}

  @override
  void visitChildren(Visitor v) {}

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('...');
  }

  @override
  String toString() {
    return 'MapPatternRestEntry(${toStringInternal()})';
  }
}

/// Kinds of lowerings of relational pattern operations.
enum RelationalAccessKind {
  /// Operator defined by an interface member.
  Instance,

  /// Operator defined by an extension or extension type member.
  Static,

  /// Operator accessed on a receiver of type `dynamic`.
  Dynamic,

  /// Operator accessed on a receiver of type `Never`.
  Never,

  /// Operator accessed on a receiver of an invalid type.
  Invalid,
}

/// Kinds of lowerings of objects pattern property access.
enum ObjectAccessKind {
  /// Property defined by an `Object` member.
  Object,

  /// Property defined by an interface member.
  Instance,

  /// Property defined by an extension member.
  Extension,

  /// Property defined by an extension type member.
  ExtensionType,

  /// Named record field property.
  RecordNamed,

  /// Positional record field property.
  RecordIndexed,

  /// Property accessed on a receiver of type `dynamic`.
  Dynamic,

  /// Property accessed on a receiver of type `Never`.
  Never,

  /// Property accessed on a receiver of an invalid type.
  Invalid,

  /// Access of `call` on a function.
  FunctionTearOff,

  /// Erroneous property access.
  Error,

  /// Access of an extension type representation field.
  Direct,
}

/// A [Pattern] with an optional guard [Expression].
class PatternGuard extends TreeNode {
  Pattern pattern;
  Expression? guard;

  new(this.pattern, [this.guard]) {
    pattern.parent = this;
    guard?.parent = this;
  }

  @override
  R accept<R>(TreeVisitor<R> v) {
    return v.visitPatternGuard(this);
  }

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
    return v.visitPatternGuard(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
    if (guard != null) {
      guard = v.transform(guard!)..parent = this;
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
    if (guard != null) {
      guard = v.transformOrRemoveExpression(guard!)?..parent = this;
    }
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
    guard?.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    pattern.toTextInternal(printer);
    if (guard != null) {
      printer.write(' when ');
      printer.writeExpression(guard!);
    }
  }

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

class PatternSwitchCase extends TreeNode implements SwitchCase {
  final List<int> caseOffsets;
  final List<PatternGuard> patternGuards;
  // TODO(johnniwinther): Handle this through serialization. Currently this
  // cannot be serialized because we have to way of referring to arbitrary
  // statements.
  // TODO(johnniwinther): Make this a list of [ContinueSwitchStatement]s.
  final List<Statement> labelUsers = [];

  @override
  Statement body;

  @override
  bool isDefault;

  bool hasLabel;

  final List<DeclaredVariable> jointVariables;

  // TODO(johnniwinther): Serialize this field.
  final List<int>? jointVariableFirstUseOffsets;

  new(
    this.caseOffsets,
    this.patternGuards,
    this.body, {
    required this.isDefault,
    required this.hasLabel,
    required this.jointVariables,
    required this.jointVariableFirstUseOffsets,
  }) {
    setParents(patternGuards, this);
    setParents(jointVariables, this);
    body.parent = this;
  }

  @override
  List<Expression> get expressions =>
      throw new UnimplementedError('PatternSwitchCase.expressions');

  @override
  List<int> get expressionOffsets =>
      throw new UnimplementedError('PatternSwitchCase.expressionOffsets');

  @override
  R accept<R>(TreeVisitor<R> v) {
    return v.visitPatternSwitchCase(this);
  }

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
    return v.visitPatternSwitchCase(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    v.transformList(patternGuards, this);
    body = v.transform(body)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    v.transformList(patternGuards, this, dummyPatternGuard);
    body = v.transform(body)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    visitList(patternGuards, v);
    body.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    for (int index = 0; index < patternGuards.length; index++) {
      if (index > 0) {
        printer.newLine();
      }
      printer.write('case ');
      patternGuards[index].toTextInternal(printer);
      printer.write(':');
    }
    if (isDefault) {
      if (patternGuards.isNotEmpty) {
        printer.newLine();
      }
      printer.write('default:');
    }
    printer.incIndentation();
    Statement? block = body;
    if (block is Block) {
      for (Statement statement in block.statements) {
        printer.newLine();
        printer.writeStatement(statement);
      }
    } else {
      printer.write(' ');
      printer.writeStatement(body);
    }
    printer.decIndentation();
  }

  @override
  String toString() {
    return "PatternSwitchCase(${toStringInternal()})";
  }
}

class PatternSwitchStatement extends Statement implements SwitchStatement {
  @override
  Expression expression;

  @override
  final List<PatternSwitchCase> cases;

  /// The type of the [expression].
  ///
  /// This is set during inference.
  @override
  DartType? expressionTypeInternal;

  /// `true` if the last case terminates.
  ///
  /// This is set during inference.
  // TODO(johnniwinther): Serialize this.
  bool lastCaseTerminates = false;

  new(this.expression, this.cases) {
    expression.parent = this;
    setParents(cases, this);
  }

  @override
  DartType get expressionType {
    assert(
      expressionTypeInternal != null,
      "Expression type hasn't been computed for $this.",
    );
    return expressionTypeInternal!;
  }

  @override
  void set expressionType(DartType value) {
    expressionTypeInternal = value;
  }

  @override
  bool isExplicitlyExhaustive = false;

  /// Whether the switch has a `default` case.
  @override
  bool get hasDefault {
    // TODO(johnniwinther): Establish this, even for erroneous cases.
    //assert(cases.every((c) => c == cases.last || !c.isDefault));
    return cases.isNotEmpty && cases.last.isDefault;
  }

  @override
  bool get isExhaustive => throw new UnimplementedError();

  @override
  R accept<R>(StatementVisitor<R> v) {
    return v.visitPatternSwitchStatement(this);
  }

  @override
  R accept1<R, A>(StatementVisitor1<R, A> v, A arg) {
    return v.visitPatternSwitchStatement(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    expression = v.transform(expression)..parent = this;
    v.transformList(cases, this);
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    expression = v.transform(expression)..parent = this;
    v.transformList(cases, this, dummyPatternSwitchCase);
  }

  @override
  void visitChildren(Visitor v) {
    expression.accept(v);
    visitList(cases, v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('switch (');
    printer.writeExpression(expression);
    printer.write(') {');
    printer.incIndentation();
    for (SwitchCase switchCase in cases) {
      printer.newLine();
      printer.writeSwitchCase(switchCase);
    }
    printer.decIndentation();
    printer.newLine();
    printer.write('}');
  }

  @override
  String toString() {
    return "PatternSwitchStatement(${toStringInternal()})";
  }
}

class SwitchExpressionCase extends TreeNode {
  PatternGuard patternGuard;
  Expression expression;

  new(this.patternGuard, this.expression) {
    patternGuard.parent = this;
    expression.parent = this;
  }

  @override
  R accept<R>(TreeVisitor<R> v) {
    return v.visitSwitchExpressionCase(this);
  }

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
    return v.visitSwitchExpressionCase(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    patternGuard = v.transform(patternGuard)..parent = this;
    expression = v.transform(expression)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    patternGuard = v.transform(patternGuard)..parent = this;
    expression = v.transform(expression)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    patternGuard.accept(v);
    expression.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('case ');
    patternGuard.toTextInternal(printer);
    printer.write(' => ');
    printer.writeExpression(expression);
  }

  @override
  String toString() {
    return 'SwitchExpressionCase(${toStringInternal()})';
  }
}

class SwitchExpression extends Expression {
  Expression expression;
  final List<SwitchExpressionCase> cases;

  /// The type of the [expression].
  ///
  /// This is set during inference.
  DartType? expressionType;

  /// The resulting type of the switch expression.
  ///
  /// This is set during inference.
  DartType? staticType;

  new(this.expression, this.cases) {
    expression.parent = this;
    setParents(cases, this);
  }

  @override
  R accept<R>(ExpressionVisitor<R> v) {
    return v.visitSwitchExpression(this);
  }

  @override
  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) {
    return v.visitSwitchExpression(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    expression = v.transform(expression)..parent = this;
    v.transformList(cases, this);
    if (staticType != null) {
      staticType = v.visitDartType(staticType!);
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    expression = v.transform(expression)..parent = this;
    v.transformList(cases, this, dummySwitchExpressionCase);
    if (staticType != null) {
      staticType = v.visitDartType(staticType!, cannotRemoveSentinel);
    }
  }

  @override
  void visitChildren(Visitor v) {
    expression.accept(v);
    visitList(cases, v);
    staticType?.accept(v);
  }

  @override
  DartType getStaticTypeInternal(StaticTypeContext context) => staticType!;

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('switch (');
    printer.writeExpression(expression);
    printer.write(') {');
    String comma = ' ';
    for (SwitchExpressionCase switchCase in cases) {
      printer.write(comma);
      switchCase.toTextInternal(printer);
      comma = ', ';
    }
    printer.write(' }');
  }

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

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

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  new(this.pattern, this.initializer, {required this.isFinal}) {
    pattern.parent = this;
    initializer.parent = this;
  }

  @override
  R accept<R>(StatementVisitor<R> v) {
    return v.visitPatternVariableDeclaration(this);
  }

  @override
  R accept1<R, A>(StatementVisitor1<R, A> v, A arg) {
    return v.visitPatternVariableDeclaration(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
    initializer = v.transform(initializer)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
    initializer = v.transform(initializer)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
    initializer.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    if (isFinal) {
      printer.write('final ');
    } else {
      printer.write('var ');
    }
    pattern.toTextInternal(printer);
    printer.write(" = ");
    printer.writeExpression(initializer);
    printer.write(';');
  }

  @override
  String toString() {
    return "PatternVariableDeclaration(${toStringInternal()})";
  }
}

class PatternAssignment extends Expression {
  Pattern pattern;
  Expression expression;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  new(this.pattern, this.expression) {
    pattern.parent = this;
    expression.parent = this;
  }

  @override
  R accept<R>(ExpressionVisitor<R> v) {
    return v.visitPatternAssignment(this);
  }

  @override
  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) {
    return v.visitPatternAssignment(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    pattern = v.transform(pattern)..parent = this;
    expression = v.transform(expression)..parent = this;
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    pattern = v.transform(pattern)..parent = this;
    expression = v.transform(expression)..parent = this;
  }

  @override
  void visitChildren(Visitor v) {
    pattern.accept(v);
    expression.accept(v);
  }

  @override
  DartType getStaticTypeInternal(StaticTypeContext context) {
    return expression.getStaticType(context);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    pattern.toTextInternal(printer);
    printer.write(' = ');
    printer.writeExpression(expression);
  }

  @override
  String toString() {
    return "PatternAssignment(${toStringInternal()})";
  }
}

/// Statement for a if-case statements:
///
///     if (expression case pattern) then
///     if (expression case pattern) then else otherwise
///     if (expression case pattern when guard) then
///     if (expression case pattern when guard) then else otherwise
///
class IfCaseStatement extends Statement {
  Expression expression;
  PatternGuard patternGuard;
  Statement then;
  Statement? otherwise;

  /// The type of the expression against which this pattern is matched.
  ///
  /// This is set during inference.
  DartType? matchedValueType;

  new(this.expression, this.patternGuard, this.then, [this.otherwise]) {
    expression.parent = this;
    patternGuard.parent = this;
    then.parent = this;
    otherwise?.parent = this;
  }

  @override
  R accept<R>(StatementVisitor<R> v) {
    return v.visitIfCaseStatement(this);
  }

  @override
  R accept1<R, A>(StatementVisitor1<R, A> v, A arg) {
    return v.visitIfCaseStatement(this, arg);
  }

  @override
  void transformChildren(Transformer v) {
    expression = v.transform(expression)..parent = this;
    patternGuard = v.transform(patternGuard)..parent = this;
    then = v.transform(then)..parent = this;
    if (otherwise != null) {
      otherwise = v.transform(otherwise!)..parent = this;
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    expression = v.transform(expression)..parent = this;
    patternGuard = v.transform(patternGuard)..parent = this;
    then = v.transform(then)..parent = this;
    if (otherwise != null) {
      otherwise = v.transformOrRemoveStatement(otherwise!)?..parent = this;
    }
  }

  @override
  void visitChildren(Visitor v) {
    expression.accept(v);
    patternGuard.accept(v);
    then.accept(v);
    otherwise?.accept(v);
  }

  @override
  void toTextInternal(AstPrinter printer) {
    printer.write('if (');
    printer.writeExpression(expression);
    printer.write(' case ');
    patternGuard.toTextInternal(printer);
    printer.write(') ');
    printer.writeStatement(then);
    if (otherwise != null) {
      printer.write(' else ');
      printer.writeStatement(otherwise!);
    }
  }

  @override
  String toString() {
    return "IfCaseStatement(${toStringInternal()})";
  }
}

final Pattern dummyPattern = new ConstantPattern(dummyExpression);

final NamedPattern dummyNamedPattern = new NamedPattern('', dummyPattern);

final MapPatternEntry dummyMapPatternEntry = new MapPatternEntry(
  dummyExpression,
  dummyPattern,
);

final PatternGuard dummyPatternGuard = new PatternGuard(dummyPattern);

final PatternSwitchCase dummyPatternSwitchCase = new PatternSwitchCase(
  [],
  [],
  dummyStatement,
  isDefault: true,
  hasLabel: false,
  jointVariables: [],
  jointVariableFirstUseOffsets: null,
);

final SwitchExpressionCase dummySwitchExpressionCase = new SwitchExpressionCase(
  dummyPatternGuard,
  dummyExpression,
);
