// 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.
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:test/test.dart';

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

Expression get nullLiteral => new _NullLiteral();

Expression get this_ => new _This();

Statement assert_(Expression condition, [Expression? message]) =>
    new _Assert(condition, message);

Statement block(List<Statement> statements) => new _Block(statements);

Expression booleanLiteral(bool value) => _BooleanLiteral(value);

Statement break_([LabeledStatement? target]) => new _Break(target);

SwitchCase case_(List<Statement> body, {bool hasLabel = false}) =>
    SwitchCase._(hasLabel, new _Block(body));

/// Creates a pseudo-statement whose function is to verify that flow analysis
/// considers [variable]'s assigned state to be [expectedAssignedState].
Statement checkAssigned(Var variable, bool expectedAssignedState) =>
    new _CheckAssigned(variable, expectedAssignedState);

/// Creates a pseudo-statement whose function is to verify that flow analysis
/// considers [variable] to be un-promoted.
Statement checkNotPromoted(Var variable) => new _CheckPromoted(variable, null);

/// Creates a pseudo-statement whose function is to verify that flow analysis
/// considers [variable]'s assigned state to be promoted to [expectedTypeStr].
Statement checkPromoted(Var variable, String? expectedTypeStr) =>
    new _CheckPromoted(variable, expectedTypeStr);

/// Creates a pseudo-statement whose function is to verify that flow analysis
/// considers the current location's reachability state to be
/// [expectedReachable].
Statement checkReachable(bool expectedReachable) =>
    new _CheckReachable(expectedReachable);

/// Creates a pseudo-statement whose function is to verify that flow analysis
/// considers [variable]'s unassigned state to be [expectedUnassignedState].
Statement checkUnassigned(Var variable, bool expectedUnassignedState) =>
    new _CheckUnassigned(variable, expectedUnassignedState);

Statement continue_() => new _Continue();

Statement declare(Var variable,
        {required bool initialized,
        bool isFinal = false,
        bool isLate = false}) =>
    new _Declare(variable, initialized ? expr(variable.type.type) : null,
        isFinal, isLate);

Statement declareInitialized(Var variable, Expression initializer,
        {bool isFinal = false, bool isLate = false}) =>
    new _Declare(variable, initializer, isFinal, isLate);

Statement do_(List<Statement> body, Expression condition) =>
    _Do(block(body), condition);

/// Creates a pseudo-expression having type [typeStr] that otherwise has no
/// effect on flow analysis.
Expression expr(String typeStr) =>
    new _PlaceholderExpression(new Type(typeStr));

/// Creates a conventional `for` statement.  Optional boolean [forCollection]
/// indicates that this `for` statement is actually a collection element, so
/// `null` should be passed to [for_bodyBegin].
Statement for_(Statement? initializer, Expression? condition,
        Expression? updater, List<Statement> body,
        {bool forCollection = false}) =>
    new _For(initializer, condition, updater, block(body), forCollection);

/// 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(Expression iterable, List<Statement> body) =>
    new _ForEach(null, iterable, block(body), false);

/// 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, Expression iterable, List<Statement> body) {
  // ignore: unnecessary_null_comparison
  assert(variable != null);
  return new _ForEach(variable, iterable, block(body), true);
}

/// 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, Expression iterable, List<Statement> body) {
  // ignore: unnecessary_null_comparison
  assert(variable != null);
  return new _ForEach(variable, iterable, block(body), false);
}

/// Creates a [Statement] that, when analyzed, will cause [callback] to be
/// passed an [SsaNodeHarness] allowing the test to examine the values of
/// variables' SSA nodes.
Statement getSsaNodes(void Function(SsaNodeHarness) callback) =>
    new _GetSsaNodes(callback);

Statement if_(Expression condition, List<Statement> ifTrue,
        [List<Statement>? ifFalse]) =>
    new _If(condition, block(ifTrue), ifFalse == null ? null : block(ifFalse));

Statement implicitThis_whyNotPromoted(String staticType,
        void Function(Map<Type, NonPromotionReason>) callback) =>
    new _WhyNotPromoted_ImplicitThis(Type(staticType), callback);

Statement labeled(Statement Function(LabeledStatement) callback) {
  var labeledStatement = LabeledStatement._();
  labeledStatement._body = callback(labeledStatement);
  return labeledStatement;
}

Statement localFunction(List<Statement> body) => _LocalFunction(block(body));

Statement return_() => new _Return();

Statement switch_(Expression expression, List<SwitchCase> cases,
        {required bool isExhaustive}) =>
    new _Switch(expression, cases, isExhaustive);

Expression thisOrSuperPropertyGet(String name) =>
    new _ThisOrSuperPropertyGet(name);

Expression throw_(Expression operand) => new _Throw(operand);

TryBuilder try_(List<Statement> body) =>
    new _TryStatement(block(body), [], null);

Statement while_(Expression condition, List<Statement> body) =>
    new _While(condition, block(body));

/// 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 {
  Expression() : super._();

  /// If `this` is an expression `x`, creates the expression `x!`.
  Expression get nonNullAssert => new _NonNullAssert(this);

  /// If `this` is an expression `x`, creates the expression `!x`.
  Expression get not => new _Not(this);

  /// If `this` is an expression `x`, creates the expression `(x)`.
  Expression get parenthesized => new _ParenthesizedExpression(this);

  /// If `this` is an expression `x`, creates the statement `x;`.
  Statement get stmt => new _ExpressionStatement(this);

  /// If `this` is an expression `x`, creates the expression `x && other`.
  Expression and(Expression other) => new _Logical(this, other, isAnd: true);

  /// If `this` is an expression `x`, creates the expression `x as typeStr`.
  Expression as_(String typeStr) => new _As(this, Type(typeStr));

  /// If `this` is an expression `x`, creates the expression
  /// `x ? ifTrue : ifFalse`.
  Expression conditional(Expression ifTrue, Expression ifFalse) =>
      new _Conditional(this, ifTrue, ifFalse);

  /// If `this` is an expression `x`, creates the expression `x == other`.
  Expression eq(Expression other) => new _Equal(this, other, false);

  /// Creates an [Expression] that, when analyzed, will behave the same as
  /// `this`, but after visiting it, will cause [callback] to be passed the
  /// [ExpressionInfo] associated with it.  If the expression has no flow
  /// analysis information associated with it, `null` will be passed to
  /// [callback].
  Expression getExpressionInfo(
          void Function(ExpressionInfo<Var, Type>?) callback) =>
      new _GetExpressionInfo(this, callback);

  /// If `this` is an expression `x`, creates the expression `x ?? other`.
  Expression ifNull(Expression other) => new _IfNull(this, other);

  /// 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}) =>
      new _Is(this, Type(typeStr), isInverted);

  /// If `this` is an expression `x`, creates the expression `x is! typeStr`.
  Expression isNot(String typeStr) => _Is(this, Type(typeStr), true);

  /// If `this` is an expression `x`, creates the expression `x != other`.
  Expression notEq(Expression other) => _Equal(this, other, true);

  /// If `this` is an expression `x`, creates the expression `x?.other`.
  ///
  /// Note that in the real Dart language, the RHS of a null aware access isn't
  /// strictly speaking an expression.  However for flow analysis it suffices to
  /// model it as an expression.
  Expression nullAwareAccess(Expression other, {bool isCascaded = false}) =>
      _NullAwareAccess(this, other, isCascaded);

  /// If `this` is an expression `x`, creates the expression `x || other`.
  Expression or(Expression other) => new _Logical(this, other, isAnd: false);

  /// If `this` is an expression `x`, creates the L-value `x.name`.
  LValue property(String name) => new _Property(this, name);

  /// 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(Statement stmt) =>
      new _WrappedExpression(null, this, stmt);

  /// Creates an [Expression] that, when analyzed, will behave the same as
  /// `this`, but after visiting it, will cause [callback] to be passed the
  /// non-promotion info associated with it.  If the expression has no
  /// non-promotion info, an empty map will be passed to [callback].
  Expression whyNotPromoted(
          void Function(Map<Type, NonPromotionReason>) callback) =>
      new _WhyNotPromoted(this, callback);

  void _preVisit(AssignedVariables<Node, Var> assignedVariables);

  Type _visit(Harness h, Type context);
}

/// Test harness for creating flow analysis tests.  This class implements all
/// the [TypeOperations] needed by flow analysis, as well as other methods
/// needed for testing.
class Harness extends TypeOperations<Var, Type> {
  static const Map<String, bool> _coreSubtypes = const {
    'bool <: int': false,
    'bool <: Object': true,
    'double <: Object': true,
    'double <: num': true,
    'double <: num?': true,
    'double <: int': false,
    'double <: int?': false,
    'int <: double': false,
    'int <: int?': true,
    'int <: Iterable': false,
    'int <: List': false,
    'int <: Null': false,
    'int <: num': true,
    'int <: num?': true,
    'int <: num*': true,
    'int <: Never?': false,
    'int <: Object': true,
    'int <: Object?': true,
    'int <: String': false,
    'int? <: int': false,
    'int? <: Null': false,
    'int? <: num': false,
    'int? <: num?': true,
    'int? <: Object': false,
    'int? <: Object?': true,
    'Never <: Object?': true,
    'Null <: int': false,
    'Null <: Object': false,
    'Null <: Object?': true,
    'num <: int': false,
    'num <: Iterable': false,
    'num <: List': false,
    'num <: num?': true,
    'num <: num*': true,
    'num <: Object': true,
    'num <: Object?': true,
    'num? <: int?': false,
    'num? <: num': false,
    'num? <: num*': true,
    'num? <: Object': false,
    'num? <: Object?': true,
    'num* <: num': true,
    'num* <: num?': true,
    'num* <: Object': true,
    'num* <: Object?': true,
    'Iterable <: int': false,
    'Iterable <: num': false,
    'Iterable <: Object': true,
    'Iterable <: Object?': true,
    'List <: int': false,
    'List <: Iterable': true,
    'List <: Object': true,
    'Never <: int': true,
    'Never <: int?': true,
    'Never <: Null': true,
    'Never? <: int': false,
    'Never? <: int?': true,
    'Never? <: num?': true,
    'Never? <: Object?': true,
    'Null <: int?': true,
    'Object <: int': false,
    'Object <: int?': false,
    'Object <: List': false,
    'Object <: Null': false,
    'Object <: num': false,
    'Object <: num?': false,
    'Object <: Object?': true,
    'Object <: String': false,
    'Object? <: Object': false,
    'Object? <: int': false,
    'Object? <: int?': false,
    'Object? <: Null': false,
    'String <: int': false,
    'String <: int?': false,
    'String <: num?': false,
    'String <: Object': true,
    'String <: Object?': true,
  };

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

  late final FlowAnalysis<Node, Statement, Expression, Var, Type> _flow;

  final bool legacy;

  final Type? thisType;

  final Map<String, bool> _subtypes = Map.of(_coreSubtypes);

  final Map<String, Type> _factorResults = Map.of(_coreFactors);

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

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

  late final _typeAnalyzer = _MiniAstTypeAnalyzer(this);

  /// 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).
  final bool respectImplicitlyTypedVarInitializers;

  Harness(
      {this.legacy = false,
      String? thisType,
      this.respectImplicitlyTypedVarInitializers = true})
      : thisType = thisType == null ? null : Type(thisType);

  MiniIrBuilder get _irBuilder => _typeAnalyzer._irBuilder;

  /// Updates the harness so that when a [factor] query is invoked on types
  /// [from] and [what], [result] will be returned.
  void addFactor(String from, String what, String result) {
    var query = '$from - $what';
    _factorResults[query] = Type(result);
  }

  /// Updates the harness so that when member [memberName] is looked up on type
  /// [targetType], a member is found having the given [type].
  void addMember(String targetType, String memberName, String type) {
    var query = '$targetType.$memberName';
    _members[query] = Type(type);
  }

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

  /// Updates the harness so that when an [isSubtypeOf] query is invoked on
  /// types [leftType] and [rightType], [isSubtype] will be returned.
  void addSubtype(String leftType, String rightType, bool isSubtype) {
    var query = '$leftType <: $rightType';
    _subtypes[query] = isSubtype;
  }

  @override
  TypeClassification classifyType(Type type) {
    if (isSubtypeOf(type, Type('Object'))) {
      return TypeClassification.nonNullable;
    } else if (isSubtypeOf(type, Type('Null'))) {
      return TypeClassification.nullOrEquivalent;
    } else {
      return TypeClassification.potentiallyNullable;
    }
  }

  @override
  Type factor(Type from, Type what) {
    var query = '$from - $what';
    return _factorResults[query] ?? fail('Unknown factor query: $query');
  }

  /// Attempts to look up a member named [memberName] in the given [type].  If
  /// a member is found, returns its type.  Otherwise the test fails.
  Type getMember(Type type, String memberName) {
    var query = '$type.$memberName';
    return _members[query] ?? fail('Unknown member query: $query');
  }

  @override
  bool isNever(Type type) {
    return type.type == 'Never';
  }

  @override
  bool isSameType(Type type1, Type type2) {
    return type1.type == type2.type;
  }

  @override
  bool isSubtypeOf(Type leftType, Type rightType) {
    if (leftType.type == rightType.type) return true;
    var query = '$leftType <: $rightType';
    return _subtypes[query] ?? fail('Unknown subtype query: $query');
  }

  @override
  bool isTypeParameterType(Type type) => type is PromotedTypeVariableType;

  @override
  Type promoteToNonNull(Type type) {
    if (type.type.endsWith('?')) {
      return Type(type.type.substring(0, type.type.length - 1));
    } else if (type.type == 'Null') {
      return Type('Never');
    } else {
      return type;
    }
  }

  /// Runs the given [statements] through flow analysis, checking any assertions
  /// they contain.
  void run(List<Statement> statements) {
    var assignedVariables = AssignedVariables<Node, Var>();
    var b = block(statements);
    b._preVisit(assignedVariables);
    _flow = legacy
        ? FlowAnalysis<Node, Statement, Expression, Var, Type>.legacy(
            this, assignedVariables)
        : FlowAnalysis<Node, Statement, Expression, Var, Type>(
            this, assignedVariables,
            respectImplicitlyTypedVarInitializers:
                respectImplicitlyTypedVarInitializers);
    _typeAnalyzer.dispatchStatement(b);
    _typeAnalyzer.finish();
  }

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

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

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

  Type _lub(Type type1, Type type2) {
    if (isSameType(type1, type2)) {
      return type1;
    } else if (isSameType(promoteToNonNull(type1), type2)) {
      return type1;
    } else if (isSameType(promoteToNonNull(type2), type1)) {
      return type2;
    } else if (type1.type == 'Null' &&
        !isSameType(promoteToNonNull(type2), type2)) {
      // type2 is already nullable
      return type2;
    } else if (type2.type == 'Null' &&
        !isSameType(promoteToNonNull(type1), type1)) {
      // type1 is already nullable
      return type1;
    } else if (type1.type == 'Never') {
      return type2;
    } else if (type2.type == 'Never') {
      return type1;
    } else {
      throw UnimplementedError(
          'TODO(paulberry): least upper bound of $type1 and $type2');
    }
  }
}

class LabeledStatement extends Statement {
  late final Statement _body;

  LabeledStatement._() : super._();

  @override
  String toString() => 'labeled: $_body';

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    _body._preVisit(assignedVariables);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeLabeledStatement(this, _body);
  }
}

/// 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._();

  /// Creates an expression representing a write to this L-value.
  Expression write(Expression? value) => new _Write(this, value);

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables,
      {_LValueDisposition disposition});

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

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

  final int id;

  Node._() : id = _nextId++;

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

/// Helper class allowing tests to examine the values of variables' SSA nodes.
class SsaNodeHarness {
  final FlowAnalysis<Node, Statement, Expression, Var, Type> _flow;

  SsaNodeHarness(this._flow);

  /// Gets the SSA node associated with [variable] at the current point in
  /// control flow, or `null` if the variable has been write captured.
  SsaNode<Var, Type>? operator [](Var variable) =>
      _flow.ssaNodeForTesting(variable);
}

/// Representation of a statement in the pseudo-Dart language used for flow
/// analysis testing.
abstract class Statement extends Node {
  Statement._() : super._();

  /// If `this` is a statement `x`, creates a pseudo-expression that models
  /// execution of `x` followed by evaluation of [expr].  This can be used to
  /// test that flow analysis is in the correct state before an expression is
  /// visited.
  Expression thenExpr(Expression expr) => _WrappedExpression(this, expr, null);

  void _preVisit(AssignedVariables<Node, Var> assignedVariables);

  void _visit(Harness h);
}

/// Representation of a single case clause in a switch statement.  Use [case_]
/// to create instances of this class.
class SwitchCase {
  final bool _hasLabel;
  final _Block _body;

  SwitchCase._(this._hasLabel, this._body);

  String toString() => [
        if (_hasLabel) '<label>:',
        'case <value>:',
        ..._body.statements
      ].join(' ');

  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    _body._preVisit(assignedVariables);
  }
}

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

  Statement finally_(List<Statement> statements);
}

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

/// Representation of a local variable in the pseudo-Dart language used for flow
/// analysis testing.
class Var {
  final String name;
  final Type type;
  final bool isImplicitlyTyped;

  Var(this.name, String typeStr, {this.isImplicitlyTyped = false})
      : type = Type(typeStr);

  /// Creates an L-value representing a reference to this variable.
  LValue get expr => new _VariableReference(this, null);

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

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

  /// Creates an expression representing a write to this variable.
  Expression write(Expression? value) => expr.write(value);
}

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

  _As(this.target, this.type);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    target._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzeTypeCast(this, target, type);
  }
}

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

  _Assert(this.condition, this.message) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    condition._preVisit(assignedVariables);
    message?._preVisit(assignedVariables);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeAssertStatement(condition, message);
    h._irBuilder.apply('assert', 2);
  }
}

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

  _Block(this.statements) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    for (var statement in statements) {
      statement._preVisit(assignedVariables);
    }
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeBlock(statements);
    h._irBuilder.apply('block', statements.length);
  }
}

class _BooleanLiteral extends Expression {
  final bool value;

  _BooleanLiteral(this.value);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeBoolLiteral(this, value);
    h._irBuilder.atom('$value');
    return type;
  }
}

class _Break extends Statement {
  final LabeledStatement? target;

  _Break(this.target) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeBreakStatement(target);
    h._irBuilder.apply('break', 0);
  }
}

/// Representation of a single catch clause in a try/catch statement.  Use
/// [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);

  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(AssignedVariables<Node, Var> assignedVariables) {
    _body._preVisit(assignedVariables);
  }
}

class _CheckAssigned extends Statement {
  final Var variable;
  final bool expectedAssignedState;

  _CheckAssigned(this.variable, this.expectedAssignedState) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    expect(h._flow.isAssigned(variable), expectedAssignedState);
    h._irBuilder.atom('null');
  }
}

class _CheckPromoted extends Statement {
  final Var variable;
  final String? expectedTypeStr;
  final StackTrace _creationTrace = StackTrace.current;

  _CheckPromoted(this.variable, this.expectedTypeStr) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    var promotedType = h._flow.promotedType(variable);
    expect(promotedType?.type, expectedTypeStr, reason: '$_creationTrace');
    h._irBuilder.atom('null');
  }
}

class _CheckReachable extends Statement {
  final bool expectedReachable;

  _CheckReachable(this.expectedReachable) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    expect(h._flow.isReachable, expectedReachable);
    h._irBuilder.atom('null');
  }
}

class _CheckUnassigned extends Statement {
  final Var variable;
  final bool expectedUnassignedState;

  _CheckUnassigned(this.variable, this.expectedUnassignedState) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    expect(h._flow.isUnassigned(variable), expectedUnassignedState);
    h._irBuilder.atom('null');
  }
}

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

  _Conditional(this.condition, this.ifTrue, this.ifFalse);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    condition._preVisit(assignedVariables);
    assignedVariables.beginNode();
    ifTrue._preVisit(assignedVariables);
    assignedVariables.endNode(this);
    ifFalse._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer
        .analyzeConditionalExpression(this, condition, ifTrue, ifFalse);
    h._irBuilder.apply('if', 3);
    return type;
  }
}

class _Continue extends Statement {
  _Continue() : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeContinueStatement();
    h._irBuilder.apply('continue', 0);
  }
}

class _Declare extends Statement {
  final Var variable;
  final Expression? initializer;
  final bool isFinal;
  final bool isLate;

  _Declare(this.variable, this.initializer, this.isFinal, this.isLate)
      : super._();

  @override
  String toString() {
    var latePart = isLate ? 'late ' : '';
    var finalPart = isFinal ? 'final ' : '';
    var initializerPart = initializer != null ? ' = $initializer' : '';
    return '$latePart$finalPart$variable${initializerPart};';
  }

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    initializer?._preVisit(assignedVariables);
  }

  @override
  void _visit(Harness h) {
    h._irBuilder.atom(variable.name);
    h._typeAnalyzer.analyzeVariableDeclaration(
        this, variable.type, variable, initializer,
        isFinal: isFinal, isLate: isLate);
    h._irBuilder.apply(
        ['declare', if (isLate) 'late', if (isFinal) 'final'].join('_'), 2);
  }
}

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

  _Do(this.body, this.condition) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    assignedVariables.beginNode();
    body._preVisit(assignedVariables);
    condition._preVisit(assignedVariables);
    assignedVariables.endNode(this);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeDoLoop(this, body, condition);
    h._irBuilder.apply('do', 2);
  }
}

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

  _Equal(this.lhs, this.rhs, this.isInverted);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    lhs._preVisit(assignedVariables);
    rhs._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var operatorName = isInverted ? '!=' : '==';
    var type =
        h._typeAnalyzer.analyzeBinaryExpression(this, lhs, operatorName, rhs);
    h._irBuilder.apply(operatorName, 2);
    return type;
  }
}

class _ExpressionStatement extends Statement {
  final Expression expr;

  _ExpressionStatement(this.expr) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    expr._preVisit(assignedVariables);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeExpressionStatement(expr);
  }
}

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)
      : super._();

  @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 _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    initializer?._preVisit(assignedVariables);
    assignedVariables.beginNode();
    condition?._preVisit(assignedVariables);
    body._preVisit(assignedVariables);
    updater?._preVisit(assignedVariables);
    assignedVariables.endNode(this);
  }

  @override
  void _visit(Harness h) {
    if (initializer != null) {
      h._typeAnalyzer.dispatchStatement(initializer!);
    } else {
      h._typeAnalyzer.handleNoInitializer();
    }
    h._flow.for_conditionBegin(this);
    if (condition != null) {
      h._typeAnalyzer.analyzeExpression(condition!);
    } else {
      h._typeAnalyzer.handleNoCondition();
    }
    h._flow.for_bodyBegin(forCollection ? null : this, condition);
    h._typeAnalyzer._visitLoopBody(this, body);
    h._flow.for_updaterBegin();
    if (updater != null) {
      h._typeAnalyzer.analyzeExpression(updater!);
    } else {
      h._typeAnalyzer.handleNoStatement();
    }
    h._flow.for_end();
    h._irBuilder.apply('for', 4);
  }
}

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)
      : super._();

  @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 _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    iterable._preVisit(assignedVariables);
    if (variable != null) {
      if (declaresVariable) {
        assignedVariables.declare(variable!);
      } else {
        assignedVariables.write(variable!);
      }
    }
    assignedVariables.beginNode();
    body._preVisit(assignedVariables);
    assignedVariables.endNode(this);
  }

  @override
  void _visit(Harness h) {
    var iteratedType =
        h._getIteratedType(h._typeAnalyzer.analyzeExpression(iterable));
    h._flow.forEach_bodyBegin(this);
    var variable = this.variable;
    if (variable != null && !declaresVariable) {
      h._flow.write(this, variable, iteratedType, null);
    }
    h._typeAnalyzer._visitLoopBody(this, body);
    h._flow.forEach_end();
    h._irBuilder.apply('forEach', 2);
  }
}

class _GetExpressionInfo extends Expression {
  final Expression target;

  final void Function(ExpressionInfo<Var, Type>?) callback;

  _GetExpressionInfo(this.target, this.callback);

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    target._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeExpression(target);
    h._flow.forwardExpression(this, target);
    callback(h._flow.expressionInfoForTesting(this));
    return type;
  }
}

class _GetSsaNodes extends Statement {
  final void Function(SsaNodeHarness) callback;

  _GetSsaNodes(this.callback) : super._();

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    callback(SsaNodeHarness(h._flow));
    h._irBuilder.atom('null');
  }
}

class _If extends Statement {
  final Expression condition;
  final Statement ifTrue;
  final Statement? ifFalse;

  _If(this.condition, this.ifTrue, this.ifFalse) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    condition._preVisit(assignedVariables);
    assignedVariables.beginNode();
    ifTrue._preVisit(assignedVariables);
    assignedVariables.endNode(this);
    ifFalse?._preVisit(assignedVariables);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeIfStatement(this, condition, ifTrue, ifFalse);
    h._irBuilder.apply('if', 3);
  }
}

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

  _IfNull(this.lhs, this.rhs);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    lhs._preVisit(assignedVariables);
    rhs._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeIfNullExpression(this, lhs, rhs);
    h._irBuilder.apply('ifNull', 2);
    return type;
  }
}

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

  _Is(this.target, this.type, this.isInverted);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    target._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer
        .analyzeTypeTest(this, target, type, isInverted: isInverted);
  }
}

class _LocalFunction extends Statement {
  final Statement body;

  _LocalFunction(this.body) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    assignedVariables.beginNode();
    body._preVisit(assignedVariables);
    assignedVariables.endNode(this, isClosureOrLateVariableInitializer: true);
  }

  @override
  void _visit(Harness h) {
    h._flow.functionExpression_begin(this);
    h._typeAnalyzer.dispatchStatement(body);
    h._flow.functionExpression_end();
  }
}

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

  _Logical(this.lhs, this.rhs, {required this.isAnd});

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    lhs._preVisit(assignedVariables);
    assignedVariables.beginNode();
    rhs._preVisit(assignedVariables);
    assignedVariables.endNode(this);
  }

  @override
  Type _visit(Harness h, Type context) {
    var operatorName = isAnd ? '&&' : '||';
    var type =
        h._typeAnalyzer.analyzeBinaryExpression(this, lhs, operatorName, rhs);
    h._irBuilder.apply(operatorName, 2);
    return 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 _MiniAstTypeAnalyzer {
  final Harness _harness;

  Statement? _currentBreakTarget;

  Statement? _currentContinueTarget;

  final _irBuilder = MiniIrBuilder();

  late final Type boolType = Type('bool');

  late final Type neverType = Type('Never');

  late final Type nullType = Type('Null');

  late final Type unknownType = Type('?');

  _MiniAstTypeAnalyzer(this._harness);

  FlowAnalysis<Node, Statement, Expression, Var, Type> get flow =>
      _harness._flow;

  Type get thisType => _harness.thisType!;

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

  Type 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);
    if (isEquals) {
      flow.equalityOp_rightBegin(lhs, leftType);
    } else if (isLogical) {
      flow.logicalBinaryOp_rightBegin(lhs, node, isAnd: isAnd);
    }
    var rightType = analyzeExpression(rhs);
    if (isEquals) {
      flow.equalityOp_end(node, rhs, rightType, notEqual: isNot);
    } else if (isLogical) {
      flow.logicalBinaryOp_end(node, rhs, isAnd: isAnd);
    }
    return boolType;
  }

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

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

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

  Type analyzeConditionalExpression(Expression node, Expression condition,
      Expression ifTrue, Expression ifFalse) {
    flow.conditional_conditionBegin();
    analyzeExpression(condition);
    flow.conditional_thenBegin(condition, node);
    var ifTrueType = analyzeExpression(ifTrue);
    flow.conditional_elseBegin(ifTrue);
    var ifFalseType = analyzeExpression(ifFalse);
    flow.conditional_end(node, ifFalse);
    return leastUpperBound(ifTrueType, ifFalseType);
  }

  void analyzeContinueStatement() {
    flow.handleContinue(_currentContinueTarget!);
  }

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

  Type analyzeExpression(Expression expression, [Type? context]) {
    // TODO(paulberry): make the [context] argument required.
    context ??= unknownType;
    return dispatchExpression(expression, context);
  }

  void analyzeExpressionStatement(Expression expression) {
    analyzeExpression(expression);
  }

  Type analyzeIfNullExpression(
      Expression node, Expression lhs, Expression rhs) {
    var leftType = analyzeExpression(lhs);
    flow.ifNullExpression_rightBegin(lhs, leftType);
    var rightType = analyzeExpression(rhs);
    flow.ifNullExpression_end();
    return leastUpperBound(
        flow.typeOperations.promoteToNonNull(leftType), rightType);
  }

  void analyzeIfStatement(Statement node, Expression condition,
      Statement ifTrue, Statement? ifFalse) {
    flow.ifStatement_conditionBegin();
    analyzeExpression(condition);
    flow.ifStatement_thenBegin(condition, node);
    dispatchStatement(ifTrue);
    if (ifFalse == null) {
      handleNoStatement();
      flow.ifStatement_end(false);
    } else {
      flow.ifStatement_elseBegin();
      dispatchStatement(ifFalse);
      flow.ifStatement_end(true);
    }
  }

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

  Type analyzeLogicalNot(Expression node, Expression expression) {
    analyzeExpression(expression);
    flow.logicalNot_end(node, expression);
    return boolType;
  }

  Type analyzeNonNullAssert(Expression node, Expression expression) {
    var type = analyzeExpression(expression);
    flow.nonNullAssert_end(expression);
    return flow.typeOperations.promoteToNonNull(type);
  }

  Type analyzeNullLiteral(Expression node) {
    flow.nullLiteral(node);
    return nullType;
  }

  Type analyzeParenthesizedExpression(Expression node, Expression expression) {
    var type = analyzeExpression(expression);
    flow.parenthesizedExpression(node, expression);
    return type;
  }

  Type analyzePropertyGet(
      Expression node, Expression receiver, String propertyName) {
    var receiverType = analyzeExpression(receiver);
    var type = _lookupMember(node, receiverType, propertyName);
    flow.propertyGet(node, receiver, propertyName, propertyName, type);
    return type;
  }

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

  void analyzeSwitchStatement(
      _Switch node, Expression expression, List<SwitchCase> cases) {
    analyzeExpression(expression);
    flow.switchStatement_expressionEnd(node);
    var previousBreakTarget = _currentBreakTarget;
    _currentBreakTarget = node;
    for (var case_ in cases) {
      flow.switchStatement_beginCase(case_._hasLabel, node);
      dispatchStatement(case_._body);
    }
    _currentBreakTarget = previousBreakTarget;
    flow.switchStatement_end(isSwitchExhaustive(node));
  }

  Type analyzeThis(Expression node) {
    var thisType = this.thisType;
    flow.thisOrSuper(node, thisType);
    return thisType;
  }

  Type analyzeThisPropertyGet(Expression node, String propertyName) {
    var type = _lookupMember(node, thisType, propertyName);
    flow.thisOrSuperPropertyGet(node, propertyName, propertyName, type);
    return type;
  }

  Type analyzeThrow(Expression node, Expression expression) {
    analyzeExpression(expression);
    flow.handleExit();
    return 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();
    }
  }

  Type analyzeTypeCast(Expression node, Expression expression, Type type) {
    analyzeExpression(expression);
    flow.asExpression_end(expression, type);
    return type;
  }

  Type analyzeTypeTest(Expression node, Expression expression, Type type,
      {bool isInverted = false}) {
    analyzeExpression(expression);
    flow.isExpression_end(node, expression, isInverted, type);
    return boolType;
  }

  void analyzeVariableDeclaration(
      Statement node, Type type, Var variable, Expression? initializer,
      {required bool isFinal, required bool isLate}) {
    if (initializer == null) {
      handleNoInitializer();
      flow.declare(variable, false);
    } else {
      var initializerType = analyzeExpression(initializer);
      flow.declare(variable, true);
      flow.initialize(variable, initializerType, initializer,
          isFinal: isFinal,
          isLate: isLate,
          isImplicitlyTyped: variable.isImplicitlyTyped);
    }
  }

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

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

  Type dispatchExpression(Expression expression, Type context) =>
      _irBuilder.guard(expression, () => expression._visit(_harness, context));

  void dispatchStatement(Statement statement) =>
      _irBuilder.guard(statement, () => statement._visit(_harness));

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

  void handleNoCondition() {
    _irBuilder.atom('true');
  }

  void handleNoInitializer() {
    _irBuilder.atom('uninitialized');
  }

  void handleNoMessage() {
    _irBuilder.atom('failure');
  }

  void handleNoStatement() {
    _irBuilder.atom('noop');
  }

  bool isSwitchExhaustive(_Switch node) {
    return node.isExhaustive;
  }

  Type leastUpperBound(Type t1, Type t2) => _harness._lub(t1, t2);

  Type lookupInterfaceMember(Node node, Type receiverType, String memberName) {
    return _harness.getMember(receiverType, memberName);
  }

  Type _lookupMember(Expression node, Type receiverType, String memberName) {
    return lookupInterfaceMember(node, receiverType, memberName);
  }

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

class _NonNullAssert extends Expression {
  final Expression operand;

  _NonNullAssert(this.operand);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    operand._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzeNonNullAssert(this, operand);
  }
}

class _Not extends Expression {
  final Expression operand;

  _Not(this.operand);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    operand._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzeLogicalNot(this, operand);
  }
}

class _NullAwareAccess extends Expression {
  static String _fakeMethodName = 'm';

  final Expression lhs;
  final Expression rhs;
  final bool isCascaded;

  _NullAwareAccess(this.lhs, this.rhs, this.isCascaded);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    lhs._preVisit(assignedVariables);
    rhs._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var lhsType = h._typeAnalyzer.analyzeExpression(lhs);
    h._flow.nullAwareAccess_rightBegin(isCascaded ? null : lhs, lhsType);
    var rhsType = h._typeAnalyzer.analyzeExpression(rhs);
    h._flow.nullAwareAccess_end();
    var type = h._lub(rhsType, Type('Null'));
    h._irBuilder.apply(_fakeMethodName, 2);
    return type;
  }
}

class _NullLiteral extends Expression {
  _NullLiteral();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeNullLiteral(this);
    h._irBuilder.atom('null');
    return type;
  }
}

class _ParenthesizedExpression extends Expression {
  final Expression expr;

  _ParenthesizedExpression(this.expr);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    expr._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzeParenthesizedExpression(this, expr);
  }
}

class _PlaceholderExpression extends Expression {
  final Type type;

  _PlaceholderExpression(this.type);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  Type _visit(Harness h, Type context) {
    h._irBuilder.atom(type.type);
    h._irBuilder.apply('expr', 1);
    return type;
  }
}

class _Property extends LValue {
  final Expression target;

  final String propertyName;

  _Property(this.target, this.propertyName) : super._();

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables,
      {_LValueDisposition disposition = _LValueDisposition.read}) {
    target._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzePropertyGet(this, target, propertyName);
  }

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

class _Return extends Statement {
  _Return() : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeReturnStatement();
    h._irBuilder.apply('return', 0);
  }
}

class _Switch extends Statement {
  final Expression expression;
  final List<SwitchCase> cases;
  final bool isExhaustive;

  _Switch(this.expression, this.cases, this.isExhaustive) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    expression._preVisit(assignedVariables);
    assignedVariables.beginNode();
    for (var case_ in cases) {
      case_._preVisit(assignedVariables);
    }
    assignedVariables.endNode(this);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeSwitchStatement(this, expression, cases);
    h._irBuilder.apply('switch', cases.length + 1);
  }
}

class _This extends Expression {
  @override
  String toString() => 'this';

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeThis(this);
    h._irBuilder.atom('this');
    return type;
  }
}

class _ThisOrSuperPropertyGet extends Expression {
  final String propertyName;

  _ThisOrSuperPropertyGet(this.propertyName);

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeThisPropertyGet(this, propertyName);
    h._irBuilder.atom('this.$propertyName');
    return type;
  }
}

class _Throw extends Expression {
  final Expression operand;

  _Throw(this.operand);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    operand._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    return h._typeAnalyzer.analyzeThrow(this, operand);
  }
}

class _TryStatement extends TryStatement {
  final Statement _body;
  final List<_CatchClause> _catches;
  final Statement? _finally;

  _TryStatement(this._body, this._catches, this._finally) : super._();

  @override
  TryStatement catch_(
      {Var? exception, Var? stackTrace, required List<Statement> body}) {
    assert(_finally == null, 'catch after finally');
    return _TryStatement(_body,
        [..._catches, _CatchClause(block(body), exception, stackTrace)], null);
  }

  @override
  Statement finally_(List<Statement> statements) {
    assert(_finally == null, 'multiple finally clauses');
    return _TryStatement(_body, _catches, block(statements));
  }

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    if (_finally != null) {
      assignedVariables.beginNode();
    }
    if (_catches.isNotEmpty) {
      assignedVariables.beginNode();
    }
    _body._preVisit(assignedVariables);
    assignedVariables.endNode(_body);
    for (var catch_ in _catches) {
      catch_._preVisit(assignedVariables);
    }
    if (_finally != null) {
      if (_catches.isNotEmpty) {
        assignedVariables.endNode(this);
      }
      _finally!._preVisit(assignedVariables);
    }
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeTryStatement(this, _body, _catches, _finally);
    h._irBuilder.apply('try', 2 + _catches.length);
  }
}

class _VariableReference extends LValue {
  final Var variable;

  final void Function(Type?)? callback;

  _VariableReference(this.variable, this.callback) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables,
      {_LValueDisposition disposition = _LValueDisposition.read}) {
    if (disposition != _LValueDisposition.write) {
      assignedVariables.read(variable);
    }
    if (disposition != _LValueDisposition.read) {
      assignedVariables.write(variable);
    }
  }

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeVariableGet(this, variable, callback);
    h._irBuilder.atom(variable.name);
    return type;
  }

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

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

  _While(this.condition, this.body) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    assignedVariables.beginNode();
    condition._preVisit(assignedVariables);
    body._preVisit(assignedVariables);
    assignedVariables.endNode(this);
  }

  @override
  void _visit(Harness h) {
    h._typeAnalyzer.analyzeWhileLoop(this, condition, body);
    h._irBuilder.apply('while', 2);
  }
}

class _WhyNotPromoted extends Expression {
  final Expression target;

  final void Function(Map<Type, NonPromotionReason>) callback;

  _WhyNotPromoted(this.target, this.callback);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    target._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    var type = h._typeAnalyzer.analyzeExpression(target);
    h._flow.forwardExpression(this, target);
    Type.withComparisonsAllowed(() {
      callback(h._flow.whyNotPromoted(this)());
    });
    return type;
  }
}

class _WhyNotPromoted_ImplicitThis extends Statement {
  final Type staticType;

  final void Function(Map<Type, NonPromotionReason>) callback;

  _WhyNotPromoted_ImplicitThis(this.staticType, this.callback) : super._();

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}

  @override
  void _visit(Harness h) {
    Type.withComparisonsAllowed(() {
      callback(h._flow.whyNotPromotedImplicitThis(staticType)());
    });
    h._irBuilder.atom('noop');
  }
}

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

  _WrappedExpression(this.before, this.expr, this.after);

  @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
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    before?._preVisit(assignedVariables);
    expr._preVisit(assignedVariables);
    after?._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    late MiniIrTmp beforeTmp;
    if (before != null) {
      h._typeAnalyzer.dispatchStatement(before!);
      beforeTmp = h._irBuilder.allocateTmp();
    }
    var type = h._typeAnalyzer.analyzeExpression(expr);
    if (after != null) {
      var exprTmp = h._irBuilder.allocateTmp();
      h._typeAnalyzer.dispatchStatement(after!);
      var afterTmp = h._irBuilder.allocateTmp();
      h._irBuilder.readTmp(exprTmp);
      h._irBuilder.let(afterTmp);
      h._irBuilder.let(exprTmp);
    }
    h._flow.forwardExpression(this, expr);
    if (before != null) {
      h._irBuilder.let(beforeTmp);
    }
    return type;
  }
}

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

  _Write(this.lhs, this.rhs);

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

  @override
  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
    lhs._preVisit(assignedVariables,
        disposition: rhs == null
            ? _LValueDisposition.readWrite
            : _LValueDisposition.write);
    rhs?._preVisit(assignedVariables);
  }

  @override
  Type _visit(Harness h, Type context) {
    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);
    } else {
      type = h._typeAnalyzer.analyzeExpression(rhs);
    }
    lhs._visitWrite(h, this, type, rhs);
    return type;
  }
}
