// 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.

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/type_environment.dart';

import 'state_machine.dart' as stateMachineCodeGen;

/// This pass lifts `await` expressions to the top-level. After the pass, all
/// `await` expressions will have the form:
///
///     final $temp = await <simple expr>;
///
/// where `<simple expr>` is an expression without `await`.
///
/// `await`s in block expressions are also lifted to the statement level.
///
/// The idea is that after this pass every `await` will have a simple
/// continuation of "assign the awaited value to the variable, continue with
/// the next statement". This allows simple code generation for async inner
/// functions.
///
/// The implementation is mostly copied from the old VM async/await transformer
/// with some changes. The old pass was removed in commit 94c120a.
void transformLibraries(
    List<Library> libraries, ClassHierarchy hierarchy, CoreTypes coreTypes) {
  final typeEnv = TypeEnvironment(coreTypes, hierarchy);

  var rewriter =
      _AwaitTransformer(StatefulStaticTypeContext.stacked(typeEnv), coreTypes);

  for (var library in libraries) {
    rewriter.transform(library);
  }
}

class _AwaitTransformer extends Transformer {
  final StatefulStaticTypeContext staticTypeContext;

  final CoreTypes coreTypes;

  List<Statement> statements = <Statement>[];

  late final _ExpressionTransformer expressionTransformer;

  _AwaitTransformer(this.staticTypeContext, this.coreTypes) {
    expressionTransformer =
        _ExpressionTransformer(this, staticTypeContext, coreTypes);
  }

  @override
  TreeNode visitField(Field node) {
    staticTypeContext.enterMember(node);
    super.visitField(node);
    staticTypeContext.leaveMember(node);
    return node;
  }

  @override
  TreeNode visitConstructor(Constructor node) {
    staticTypeContext.enterMember(node);
    final result = super.visitConstructor(node);
    staticTypeContext.leaveMember(node);
    return result;
  }

  @override
  TreeNode visitProcedure(Procedure node) {
    staticTypeContext.enterMember(node);
    final result = node.isAbstract ? node : super.visitProcedure(node);
    staticTypeContext.leaveMember(node);
    return result;
  }

  @override
  TreeNode visitFunctionNode(FunctionNode node) {
    final Statement? body = node.body;
    if (body != null) {
      final transformer = _AwaitTransformer(staticTypeContext, coreTypes);
      Statement newBody = transformer.transform(body);

      final List<Statement> newStatements = [
        ...transformer.expressionTransformer.variables,
        ...transformer.statements,
      ];

      if (newStatements.isNotEmpty) {
        newBody = Block([
          ...newStatements,
          ...newBody is Block ? newBody.statements : [newBody]
        ]);
      }

      node.body = newBody..parent = node;
    }
    return node;
  }

  @override
  TreeNode visitAssertBlock(AssertBlock stmt) {
    final savedStatements = statements;
    statements = [];
    for (final stmt in stmt.statements) {
      statements.add(transform(stmt));
    }
    final newBlock = AssertBlock(statements);
    statements = savedStatements;
    return newBlock;
  }

  @override
  TreeNode visitAssertStatement(AssertStatement stmt) {
    final List<Statement> condEffects = [];
    final cond = expressionTransformer.rewrite(stmt.condition, condEffects);
    final msg = stmt.message;
    if (msg == null) {
      stmt.condition = cond..parent = stmt;
      // If the translation of the condition produced a non-empty list of
      // statements, ensure they are guarded by whether asserts are enabled.
      return condEffects.isEmpty ? stmt : AssertBlock(condEffects..add(stmt));
    }

    // The translation depends on the translation of the message.
    final List<Statement> msgEffects = [];
    stmt.message = expressionTransformer.rewrite(msg, msgEffects)
      ..parent = stmt;
    if (condEffects.isEmpty) {
      if (msgEffects.isEmpty) {
        // The condition rewrote to ([], C) and the message rewrote to ([], M).
        // The result is
        //
        // assert(C, M)
        stmt.condition = cond..parent = stmt;
        return stmt;
      } else {
        // The condition rewrote to ([], C) and the message rewrote to (S*, M)
        // where S* is non-empty.  The result is
        //
        // assert { if (C) {} else { S*; assert(false, M); }}
        stmt.condition = BoolLiteral(false)..parent = stmt;
        return AssertBlock([
          IfStatement(cond, EmptyStatement(), Block(msgEffects..add(stmt)))
        ]);
      }
    } else {
      if (msgEffects.isEmpty) {
        // The condition rewrote to (S*, C) where S* is non-empty and the
        // message rewrote to ([], M).  The result is
        //
        // assert { S*; assert(C, M); }
        stmt.condition = cond..parent = stmt;
        condEffects.add(stmt);
      } else {
        // The condition rewrote to (S0*, C) and the message rewrote to (S1*, M)
        // where both S0* and S1* are non-empty.  The result is
        //
        // assert { S0*; if (C) {} else { S1*; assert(false, M); }}
        stmt.condition = BoolLiteral(false)..parent = stmt;
        condEffects.add(
            IfStatement(cond, EmptyStatement(), Block(msgEffects..add(stmt))));
      }
      return AssertBlock(condEffects);
    }
  }

  @override
  TreeNode visitBlock(Block stmt) {
    final savedStatements = statements;
    statements = [];
    for (final statement in stmt.statements) {
      final newStatement = transform(statement);
      statements.add(newStatement);
    }
    final newBlock = Block(statements);
    statements = savedStatements;
    return newBlock;
  }

  @override
  TreeNode visitBreakStatement(BreakStatement stmt) => stmt;

  @override
  TreeNode visitContinueSwitchStatement(ContinueSwitchStatement stmt) => stmt;

  Statement visitDelimited(Statement stmt) {
    final saved = statements;
    statements = [];
    statements.add(transform(stmt));
    final result =
        statements.length == 1 ? statements.first : Block(statements);
    statements = saved;
    return result;
  }

  @override
  TreeNode visitDoStatement(DoStatement stmt) {
    Statement body = visitDelimited(stmt.body); // block or single statement
    final List<Statement> effects = [];
    stmt.condition = expressionTransformer.rewrite(stmt.condition, effects)
      ..parent = stmt;
    if (effects.isNotEmpty) {
      // The condition rewrote to a non-empty sequence of statements S* and
      // value V.  Add the statements to the end of the loop body.
      final Block block = body is Block ? body : body = Block([body]);
      for (final effect in effects) {
        block.statements.add(effect);
        effect.parent = body;
      }
    }
    stmt.body = body..parent = stmt;
    return stmt;
  }

  @override
  TreeNode visitEmptyStatement(EmptyStatement stmt) => stmt;

  @override
  TreeNode visitExpressionStatement(ExpressionStatement stmt) {
    stmt.expression = expressionTransformer.rewrite(stmt.expression, statements)
      ..parent = stmt;
    return stmt;
  }

  @override
  TreeNode visitForInStatement(ForInStatement stmt) {
    throw 'For statement at ${stmt.location}';
  }

  @override
  TreeNode visitForStatement(ForStatement stmt) {
    // Because of for-loop scoping and variable capture, it is tricky to deal
    // with await in the loop's variable initializers or update expressions.
    bool isSimple = true;
    int length = stmt.variables.length;
    List<List<Statement>> initEffects =
        List<List<Statement>>.generate(length, (int i) {
      VariableDeclaration decl = stmt.variables[i];
      List<Statement> statements = <Statement>[];
      if (decl.initializer != null) {
        decl.initializer = expressionTransformer.rewrite(
            decl.initializer!, statements)
          ..parent = decl;
      }
      isSimple = isSimple && statements.isEmpty;
      return statements;
    });

    length = stmt.updates.length;
    List<List<Statement>> updateEffects =
        List<List<Statement>>.generate(length, (int i) {
      List<Statement> statements = <Statement>[];
      stmt.updates[i] = expressionTransformer.rewrite(
          stmt.updates[i], statements)
        ..parent = stmt;
      isSimple = isSimple && statements.isEmpty;
      return statements;
    });

    Statement body = visitDelimited(stmt.body);
    Expression? cond = stmt.condition;
    List<Statement>? condEffects;
    if (cond != null) {
      condEffects = <Statement>[];
      cond = expressionTransformer.rewrite(stmt.condition!, condEffects);
    }

    if (isSimple) {
      // If the condition contains await, we use a translation like the one for
      // while loops, but leaving the variable declarations and the update
      // expressions in place.
      if (condEffects == null || condEffects.isEmpty) {
        if (cond != null) stmt.condition = cond..parent = stmt;
        stmt.body = body..parent = stmt;
        return stmt;
      } else {
        LabeledStatement labeled = LabeledStatement(stmt);
        // No condition in a for loop is the same as true.
        stmt.condition = null;
        condEffects.add(IfStatement(cond!, body, BreakStatement(labeled)));
        stmt.body = Block(condEffects)..parent = stmt;
        return labeled;
      }
    }

    // If the rewrite of the initializer or update expressions produces a
    // non-empty sequence of statements then the loop is desugared.  If the loop
    // has the form:
    //
    // label: for (Type x = init; cond; update) body
    //
    // it is translated as if it were:
    //
    // {
    //   bool first = true;
    //   Type temp;
    //   label: while (true) {
    //     Type x;
    //     if (first) {
    //       first = false;
    //       x = init;
    //     } else {
    //       x = temp;
    //       update;
    //     }
    //     if (cond) {
    //       body;
    //       temp = x;
    //     } else {
    //       break;
    //     }
    //   }
    // }

    // Place the loop variable declarations at the beginning of the body
    // statements and move their initializers to a guarded list of statements.
    // Add assignments to the loop variables from the previous iterations temp
    // variables before the updates.
    //
    // temps.first is the flag 'first'.
    List<VariableDeclaration> temps = <VariableDeclaration>[
      VariableDeclaration.forValue(BoolLiteral(true), isFinal: false)
    ];
    List<Statement> loopBody = <Statement>[];
    List<Statement> initializers = <Statement>[
      ExpressionStatement(VariableSet(temps.first, BoolLiteral(false)))
    ];
    List<Statement> updates = <Statement>[];
    List<Statement> newBody = <Statement>[body];
    for (int i = 0; i < stmt.variables.length; ++i) {
      VariableDeclaration decl = stmt.variables[i];
      temps
          .add(VariableDeclaration(null, type: decl.type, isSynthesized: true));
      loopBody.add(decl);
      if (decl.initializer != null) {
        initializers.addAll(initEffects[i]);
        initializers
            .add(ExpressionStatement(VariableSet(decl, decl.initializer!)));
        decl.initializer = null;
      }
      updates
          .add(ExpressionStatement(VariableSet(decl, VariableGet(temps.last))));
      newBody
          .add(ExpressionStatement(VariableSet(temps.last, VariableGet(decl))));
    }
    // Add the updates to their guarded list of statements.
    for (int i = 0; i < stmt.updates.length; ++i) {
      updates.addAll(updateEffects[i]);
      updates.add(ExpressionStatement(stmt.updates[i]));
    }
    // Initializers or updates could be empty.
    loopBody.add(IfStatement(
        VariableGet(temps.first), Block(initializers), Block(updates)));

    LabeledStatement labeled = LabeledStatement(null);
    if (cond != null) {
      loopBody.addAll(condEffects!);
    } else {
      cond = BoolLiteral(true);
    }
    loopBody.add(IfStatement(cond, Block(newBody), BreakStatement(labeled)));
    labeled.body = WhileStatement(BoolLiteral(true), Block(loopBody))
      ..parent = labeled;
    return Block(<Statement>[...temps, labeled]);
  }

  @override
  TreeNode visitFunctionDeclaration(FunctionDeclaration stmt) {
    stmt.function = transform(stmt.function)..parent = stmt;
    return stmt;
  }

  @override
  TreeNode visitIfStatement(IfStatement stmt) {
    stmt.condition = expressionTransformer.rewrite(stmt.condition, statements)
      ..parent = stmt;
    stmt.then = visitDelimited(stmt.then)..parent = stmt;
    if (stmt.otherwise != null) {
      stmt.otherwise = visitDelimited(stmt.otherwise!)..parent = stmt;
    }
    return stmt;
  }

  @override
  TreeNode visitLabeledStatement(LabeledStatement stmt) {
    stmt.body = visitDelimited(stmt.body)..parent = stmt;
    return stmt;
  }

  @override
  TreeNode visitReturnStatement(ReturnStatement stmt) {
    if (stmt.expression != null) {
      stmt.expression = expressionTransformer.rewrite(
          stmt.expression!, statements)
        ..parent = stmt;
    }

    return stmt;
  }

  @override
  TreeNode visitSwitchStatement(SwitchStatement stmt) {
    stmt.expression = expressionTransformer.rewrite(stmt.expression, statements)
      ..parent = stmt;
    for (final switchCase in stmt.cases) {
      // Expressions in switch cases cannot contain await so they do not need to
      // be translated.
      switchCase.body = visitDelimited(switchCase.body)..parent = switchCase;
    }
    return stmt;
  }

  @override
  TreeNode visitTryCatch(TryCatch stmt) {
    stmt.body = visitDelimited(stmt.body)..parent = stmt;
    for (final catch_ in stmt.catches) {
      // Create a fresh variable for the exception and stack trace: when a
      // catch block has an `await` we use the catch block variables to restore
      // the current exception after the `await`.
      //
      // TODO (omersa): We could mark [TreeNode]s with `await`s and only do this
      catch_.exception ??= VariableDeclaration(null,
          type: InterfaceType(coreTypes.objectClass, Nullability.nonNullable),
          isSynthesized: true)
        ..parent = catch_;
      catch_.stackTrace ??= VariableDeclaration(null,
          type:
              InterfaceType(coreTypes.stackTraceClass, Nullability.nonNullable),
          isSynthesized: true)
        ..parent = catch_;

      var body = visitDelimited(catch_.body);

      // Add uses to exception and stack trace vars so that they will be added
      // to the context if the catch block has an await.
      if (body is Block) {
        body.statements.add(
            ExpressionStatement(VariableGet(catch_.exception!))..parent = body);
        body.statements.add(ExpressionStatement(VariableGet(catch_.stackTrace!))
          ..parent = body);
      } else {
        body = Block([
          body,
          ExpressionStatement(VariableGet(catch_.exception!)),
          ExpressionStatement(VariableGet(catch_.stackTrace!)),
        ]);
      }

      catch_.body = body..parent = catch_;
    }
    return stmt;
  }

  @override
  TreeNode visitTryFinally(TryFinally stmt) {
    // TODO (omersa): Wrapped in a block to be able to get the variable
    // declarations using `parent.statements[0]` etc. when compiling the node.
    // Ideally we may want to create these variables not in kernel but during
    // code generation.

    // Variable for the finalizer block continuation.
    final continuationVar = VariableDeclaration(null,
        initializer: IntLiteral(stateMachineCodeGen.continuationFallthrough),
        type: InterfaceType(coreTypes.intClass, Nullability.nonNullable),
        isSynthesized: true);

    // When the finalizer continuation is "rethrow", this stores the exception
    // to rethrow.
    final exceptionVar = VariableDeclaration(null,
        type: InterfaceType(coreTypes.objectClass, Nullability.nonNullable),
        isSynthesized: true);

    // When the finalizer continuation is "rethrow", this stores the stack
    // trace of the exception in [exceptionVar].
    final stackTraceVar = VariableDeclaration(null,
        type: InterfaceType(coreTypes.stackTraceClass, Nullability.nonNullable),
        isSynthesized: true);

    final body = visitDelimited(stmt.body);
    var finalizer = visitDelimited(stmt.finalizer);

    // Add a use of `continuationVar` in finally so that it will be added to
    // the context
    if (finalizer is Block) {
      finalizer.statements.add(ExpressionStatement(VariableGet(continuationVar))
        ..parent = finalizer);
      finalizer.statements.add(
          ExpressionStatement(VariableGet(exceptionVar))..parent = finalizer);
      finalizer.statements.add(
          ExpressionStatement(VariableGet(stackTraceVar))..parent = finalizer);
    } else {
      finalizer = Block([
        finalizer,
        ExpressionStatement(VariableGet(continuationVar)),
        ExpressionStatement(VariableGet(exceptionVar)),
        ExpressionStatement(VariableGet(stackTraceVar)),
      ]);
    }

    return Block([
      continuationVar,
      exceptionVar,
      stackTraceVar,
      TryFinally(body, finalizer)
    ]);
  }

  @override
  TreeNode visitVariableDeclaration(VariableDeclaration stmt) {
    final initializer = stmt.initializer;
    if (initializer != null) {
      stmt.initializer = expressionTransformer.rewrite(initializer, statements)
        ..parent = stmt;
    }
    return stmt;
  }

  @override
  TreeNode visitWhileStatement(WhileStatement stmt) {
    final Statement body = visitDelimited(stmt.body);
    final List<Statement> effects = [];
    final Expression cond =
        expressionTransformer.rewrite(stmt.condition, effects);
    if (effects.isEmpty) {
      stmt.condition = cond..parent = stmt;
      stmt.body = body..parent = stmt;
      return stmt;
    } else {
      // The condition rewrote to a non-empty sequence of statements S* and
      // value V.  Rewrite the loop to:
      //
      // L: while (true) {
      //   S*
      //   if (V) {
      //     [body]
      //   else {
      //     break L;
      //   }
      // }
      final LabeledStatement labeled = LabeledStatement(stmt);
      stmt.condition = BoolLiteral(true)..parent = stmt;
      effects.add(IfStatement(cond, body, BreakStatement(labeled)));
      stmt.body = Block(effects)..parent = stmt;
      return labeled;
    }
  }

  @override
  TreeNode visitYieldStatement(YieldStatement stmt) {
    stmt.expression = expressionTransformer.rewrite(stmt.expression, statements)
      ..parent = stmt;
    return stmt;
  }

  @override
  TreeNode defaultStatement(Statement stmt) =>
      throw 'Unhandled statement: $stmt (${stmt.location})';

  @override
  TreeNode defaultExpression(Expression expr) {
    // This visits initializer expressions, annotations etc.
    final List<Statement> effects = [];
    final Expression transformedExpr =
        expressionTransformer.rewrite(expr, effects);
    if (effects.isEmpty) {
      return transformedExpr;
    } else {
      return BlockExpression(Block(effects), expr);
    }
  }
}

class _ExpressionTransformer extends Transformer {
  /// Whether we have seen an await to the right in the expression tree.
  ///
  /// Subexpressions are visited right-to-left in the reverse of evaluation
  /// order.
  ///
  /// On entry to an expression's visit method, [seenAwait] indicates whether a
  /// sibling to the right contains an await.  If so the expression will be
  /// named in a temporary variable because it is potentially live across an
  /// await.
  ///
  /// On exit from an expression's visit method, [seenAwait] indicates whether
  /// the expression itself or a sibling to the right contains an await.
  bool seenAwait = false;

  /// The (reverse order) sequence of statements that have been emitted.
  ///
  /// Transformation of an expression produces a transformed expression and a
  /// sequence of statements which are assignments to local variables, calls to
  /// helper functions, and yield points.  Only the yield points need to be a
  /// statements, and they are statements so an implementation does not have to
  /// handle unnamed expression intermediate live across yield points.
  ///
  /// The visit methods return the transformed expression and build a sequence
  /// of statements by emitting statements into this list.  This list is built
  /// in reverse because children are visited right-to-left.
  ///
  /// If an expression should be named it is named before visiting its children
  /// so the naming assignment appears in the list before all statements
  /// implementing the translation of the children.
  ///
  /// Children that are conditionally evaluated, such as some parts of logical
  /// and conditional expressions, must be delimited so that they do not emit
  /// unguarded statements into [statements].  This is implemented by setting
  /// [statements] to a fresh empty list before transforming those children.
  List<Statement> statements = <Statement>[];

  /// The number of currently live named intermediate values.
  ///
  /// This index is used to allocate names to temporary values.  Because
  /// children are visited right-to-left, names are assigned in reverse order
  /// of index.
  ///
  /// When an assignment is emitted into [statements] to name an expression
  /// before visiting its children, the index is not immediately reserved
  /// because a child can freely use the same name as its parent.  In practice,
  /// this will be the rightmost named child.
  ///
  /// After visiting the children of a named expression, [nameIndex] is set to
  /// indicate one more live value (the value of the expression) than before
  /// visiting the expression.
  ///
  /// After visiting the children of an expression that is not named,
  /// [nameIndex] may still account for names of subexpressions.
  int nameIndex = 0;

  /// Variables created for temporaries.
  final List<VariableDeclaration> variables = <VariableDeclaration>[];

  final _AwaitTransformer _statementTransformer;

  final StatefulStaticTypeContext staticTypeContext;

  final CoreTypes coreTypes;

  _ExpressionTransformer(
      this._statementTransformer, this.staticTypeContext, this.coreTypes);

  // Helpers

  /// Name an expression by emitting an assignment to a temporary variable.
  Expression name(Expression expr) {
    final DartType type = expr.getStaticType(staticTypeContext);
    final VariableDeclaration temp = allocateTemporary(nameIndex, type);
    statements.add(ExpressionStatement(VariableSet(temp, expr)));
    return castVariableGet(temp, type);
  }

  VariableDeclaration allocateTemporary(int index,
      [DartType type = const DynamicType()]) {
    if (variables.length > index) {
      // Re-using a temporary. Re-type it to dynamic if we detect reuse with
      // different type.
      if (variables[index].type != const DynamicType() &&
          variables[index].type != type) {
        variables[index].type = const DynamicType();
      }
      return variables[index];
    }
    for (var i = variables.length; i <= index; i++) {
      variables.add(VariableDeclaration(":async_temporary_$i", type: type));
    }
    return variables[index];
  }

  /// Casts a [VariableGet] with `as dynamic` if its type is not `dynamic`.
  Expression castVariableGet(VariableDeclaration variable, DartType type) {
    Expression expr = VariableGet(variable);
    if (type != const DynamicType()) {
      expr = AsExpression(expr, DynamicType());
    }
    return expr;
  }

  // Expressions

  /// Rewrite a top-level expression (top-level wrt. a statement). This is the
  /// entry-point from [_AwaitTransformer].
  ///
  /// Rewriting an expression produces a sequence of statements and an
  /// expression. The sequence of statements are added to the given list. Pass
  /// an empty list if the rewritten expression should be delimited from the
  /// surrounding context.
  //
  // TODO (omersa): We should be able to maintain the state for temporaries
  // (`nameIndex`, `variables`) in a separate class and create a new expression
  // transformer every time we transform a top-level expression. Would that
  // make the code clearer?
  Expression rewrite(Expression expression, List<Statement> outer) {
    assert(statements.isEmpty);
    final saved = seenAwait;
    seenAwait = false;
    final Expression result = transform(expression);
    outer.addAll(statements.reversed);
    statements.clear();
    seenAwait = seenAwait || saved;
    return result;
  }

  @override
  TreeNode defaultExpression(Expression expr) =>
      throw 'Unhandled expression: $expr (${expr.location})';

  @override
  TreeNode visitFunctionExpression(FunctionExpression expr) {
    expr.transformChildren(this);
    return expr;
  }

  // Simple literals. These are pure expressions so they can be evaluated after
  // an await to their right.
  @override
  TreeNode visitSymbolLiteral(SymbolLiteral expr) => expr;

  @override
  TreeNode visitTypeLiteral(TypeLiteral expr) => expr;

  @override
  TreeNode visitThisExpression(ThisExpression expr) => expr;

  @override
  TreeNode visitStringLiteral(StringLiteral expr) => expr;

  @override
  TreeNode visitIntLiteral(IntLiteral expr) => expr;

  @override
  TreeNode visitDoubleLiteral(DoubleLiteral expr) => expr;

  @override
  TreeNode visitBoolLiteral(BoolLiteral expr) => expr;

  @override
  TreeNode visitNullLiteral(NullLiteral expr) => expr;

  @override
  TreeNode visitConstantExpression(ConstantExpression expr) => expr;

  @override
  TreeNode visitCheckLibraryIsLoaded(CheckLibraryIsLoaded expr) => expr;

  @override
  TreeNode visitLoadLibrary(LoadLibrary expr) => expr;

  /// Transform expressions with no child expressions.
  Expression nullary(Expression expr) {
    if (seenAwait) {
      expr = name(expr);
      ++nameIndex;
    }
    return expr;
  }

  @override
  TreeNode visitSuperPropertyGet(SuperPropertyGet expr) => nullary(expr);

  @override
  TreeNode visitStaticGet(StaticGet expr) => nullary(expr);

  @override
  TreeNode visitStaticTearOff(StaticTearOff expr) => nullary(expr);

  @override
  TreeNode visitRethrow(Rethrow expr) => nullary(expr);

  @override
  TreeNode visitFileUriExpression(FileUriExpression expr) => unary(expr);

  @override
  TreeNode visitVariableGet(VariableGet expr) {
    Expression result = expr;
    // Getting a final or const variable is not an effect so it can be
    // evaluated after an await to its right.
    if (seenAwait && !expr.variable.isFinal && !expr.variable.isConst) {
      result = name(expr);
      ++nameIndex;
    }
    return result;
  }

  /// Transform an expression given an action to transform the children. For
  /// this purposes of the await transformer the children should generally be
  /// translated from right to left, in the reverse of evaluation order.
  Expression transformTreeNode(Expression expr, void Function() action,
      {bool alwaysName = false}) {
    final bool shouldName = alwaysName || seenAwait;

    // 1. If there is an await in a sibling to the right, emit an assignment to
    // a temporary variable before transforming the children.
    final Expression result = shouldName ? name(expr) : expr;

    // 2. Remember the number of live temporaries before transforming the
    // children.
    final int index = nameIndex;

    // 3. Transform the children. Initially they do not have an await in a
    // sibling to their right.
    seenAwait = false;
    action();

    // 4. If the expression was named then the variables used for children are
    // no longer live but the variable used for the expression is. On the other
    // hand, a sibling to the left (yet to be processed) cannot reuse any of
    // the variables used here, as the assignments in the children (here) would
    // overwrite assignments in the siblings to the left, possibly before the
    // use of the overwritten values.
    if (shouldName) {
      if (index + 1 > nameIndex) {
        nameIndex = index + 1;
      }
      seenAwait = true;
    }

    return result;
  }

  /// Transform expressions with one child expression.
  Expression unary(Expression expr) {
    return transformTreeNode(expr, () {
      expr.transformChildren(this);
    });
  }

  @override
  TreeNode visitInvalidExpression(InvalidExpression expr) => unary(expr);

  @override
  TreeNode visitVariableSet(VariableSet expr) => unary(expr);

  @override
  TreeNode visitInstanceGet(InstanceGet expr) => unary(expr);

  @override
  TreeNode visitDynamicGet(DynamicGet expr) => unary(expr);

  @override
  TreeNode visitInstanceTearOff(InstanceTearOff expr) => unary(expr);

  @override
  TreeNode visitSuperPropertySet(SuperPropertySet expr) => unary(expr);

  @override
  TreeNode visitStaticSet(StaticSet expr) => unary(expr);

  @override
  TreeNode visitNot(Not expr) => unary(expr);

  @override
  TreeNode visitIsExpression(IsExpression expr) => unary(expr);

  @override
  TreeNode visitAsExpression(AsExpression expr) => unary(expr);

  @override
  TreeNode visitThrow(Throw expr) => unary(expr);

  @override
  TreeNode visitEqualsNull(EqualsNull expr) => unary(expr);

  @override
  TreeNode visitRecordIndexGet(RecordIndexGet expr) => unary(expr);

  @override
  TreeNode visitRecordNameGet(RecordNameGet expr) => unary(expr);

  @override
  TreeNode visitNullCheck(NullCheck expr) => unary(expr);

  @override
  TreeNode visitInstantiation(Instantiation expr) => unary(expr);

  @override
  TreeNode visitInstanceSet(InstanceSet expr) {
    return transformTreeNode(expr, () {
      expr.value = transform(expr.value)..parent = expr;
      expr.receiver = transform(expr.receiver)..parent = expr;
    });
  }

  @override
  TreeNode visitDynamicSet(DynamicSet expr) {
    return transformTreeNode(expr, () {
      expr.value = transform(expr.value)..parent = expr;
      expr.receiver = transform(expr.receiver)..parent = expr;
    });
  }

  @override
  TreeNode visitArguments(Arguments args) {
    for (final named in args.named.reversed) {
      named.value = transform(named.value)..parent = named;
    }
    final positional = args.positional;
    for (var i = positional.length - 1; i >= 0; --i) {
      positional[i] = transform(positional[i])..parent = args;
    }
    return args;
  }

  @override
  TreeNode visitInstanceInvocation(InstanceInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
      expr.receiver = transform(expr.receiver)..parent = expr;
    });
  }

  @override
  TreeNode visitLocalFunctionInvocation(LocalFunctionInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
    });
  }

  @override
  TreeNode visitDynamicInvocation(DynamicInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
      expr.receiver = transform(expr.receiver)..parent = expr;
    });
  }

  @override
  TreeNode visitFunctionInvocation(FunctionInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
      expr.receiver = transform(expr.receiver)..parent = expr;
    });
  }

  @override
  TreeNode visitEqualsCall(EqualsCall expr) {
    return transformTreeNode(expr, () {
      expr.right = transform(expr.right)..parent = expr;
      expr.left = transform(expr.left)..parent = expr;
    });
  }

  @override
  TreeNode visitSuperMethodInvocation(SuperMethodInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
    });
  }

  @override
  TreeNode visitStaticInvocation(StaticInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
    });
  }

  @override
  TreeNode visitConstructorInvocation(ConstructorInvocation expr) {
    return transformTreeNode(expr, () {
      visitArguments(expr.arguments);
    });
  }

  @override
  TreeNode visitStringConcatenation(StringConcatenation expr) {
    return transformTreeNode(expr, () {
      final expressions = expr.expressions;
      for (var i = expressions.length - 1; i >= 0; --i) {
        expressions[i] = transform(expressions[i])..parent = expr;
      }
    });
  }

  @override
  TreeNode visitListLiteral(ListLiteral expr) {
    return transformTreeNode(expr, () {
      final expressions = expr.expressions;
      for (var i = expressions.length - 1; i >= 0; --i) {
        expressions[i] = transform(expr.expressions[i])..parent = expr;
      }
    });
  }

  @override
  TreeNode visitMapLiteral(MapLiteral expr) {
    return transformTreeNode(expr, () {
      for (final entry in expr.entries.reversed) {
        entry.value = transform(entry.value)..parent = entry;
        entry.key = transform(entry.key)..parent = entry;
      }
    });
  }

  @override
  TreeNode visitSetLiteral(SetLiteral expr) {
    return transformTreeNode(expr, () {
      final expressions = expr.expressions;
      for (var i = expressions.length - 1; i >= 0; --i) {
        expressions[i] = transform(expr.expressions[i])..parent = expr;
      }
    });
  }

  @override
  TreeNode visitRecordLiteral(RecordLiteral expr) {
    return transformTreeNode(expr, () {
      final named = expr.named;
      for (var i = named.length - 1; i >= 0; --i) {
        named[i] = transform(expr.named[i])..parent = expr;
      }

      final positional = expr.positional;
      for (var i = positional.length - 1; i >= 0; --i) {
        positional[i] = transform(expr.positional[i])..parent = expr;
      }
    });
  }

  // Expressions with control flow

  /// Perform an action with a given list of statements so that it cannot emit
  /// statements into the 'outer' list.
  Expression delimit(Expression Function() action, List<Statement> inner) {
    final outer = statements;
    statements = inner;
    final result = action();
    statements = outer;
    return result;
  }

  /// Make a [Block] from a reversed list of [Statement]s by reverting the
  /// statements.
  Block blockOf(List<Statement> reversedStatements) {
    return Block(reversedStatements.reversed.toList());
  }

  @override
  TreeNode visitLogicalExpression(LogicalExpression expr) {
    final bool shouldName = seenAwait;

    // Right is delimited because it is conditionally evaluated.
    final List<Statement> rightStatements = [];
    seenAwait = false;
    expr.right = delimit(() => transform(expr.right), rightStatements)
      ..parent = expr;
    final bool rightAwait = seenAwait;

    if (rightStatements.isEmpty) {
      // Easy case: right did not emit any statements.
      seenAwait = shouldName;
      return transformTreeNode(expr, () {
        expr.left = transform(expr.left)..parent = expr;
        seenAwait = seenAwait || rightAwait;
      });
    }

    // If right has emitted statements we will produce a temporary t and emit
    // for && (there is an analogous case for ||):
    //
    // t = [left] == true;
    // if (t) {
    //   t = [right] == true;
    // }

    // Recall that statements are emitted in reverse order, so first emit the
    // if statement, then the assignment of [left] == true, and then translate
    // left so any statements it emits occur after in the accumulated list
    // (that is, so they occur before in the corresponding block).
    final Block rightBody = blockOf(rightStatements);
    final InterfaceType type = staticTypeContext.typeEnvironment.coreTypes
        .boolRawType(staticTypeContext.nonNullable);
    final VariableDeclaration result = allocateTemporary(nameIndex, type);
    final objectEquals = coreTypes.objectEquals;
    rightBody.addStatement(ExpressionStatement(VariableSet(
        result,
        EqualsCall(expr.right, BoolLiteral(true),
            interfaceTarget: objectEquals,
            functionType: objectEquals.getterType as FunctionType))));
    final Statement then;
    final Statement? otherwise;
    if (expr.operatorEnum == LogicalExpressionOperator.AND) {
      then = rightBody;
      otherwise = null;
    } else {
      then = EmptyStatement();
      otherwise = rightBody;
    }
    statements.add(IfStatement(castVariableGet(result, type), then, otherwise));

    final test = EqualsCall(expr.left, BoolLiteral(true),
        interfaceTarget: objectEquals,
        functionType: objectEquals.getterType as FunctionType);
    statements.add(ExpressionStatement(VariableSet(result, test)));

    seenAwait = false;
    test.left = transform(test.left)..parent = test;

    nameIndex += 1;
    seenAwait = seenAwait || rightAwait;
    return castVariableGet(result, type);
  }

  @override
  TreeNode visitConditionalExpression(ConditionalExpression expr) {
    // Then and otherwise are delimited because they are conditionally
    // evaluated.
    final bool shouldName = seenAwait;

    final int savedNameIndex = nameIndex;

    final thenStatements = <Statement>[];
    seenAwait = false;
    expr.then = delimit(() => transform(expr.then), thenStatements)
      ..parent = expr;
    final thenAwait = seenAwait;

    final thenNameIndex = nameIndex;
    nameIndex = savedNameIndex;

    final List<Statement> otherwiseStatements = [];
    seenAwait = false;
    expr.otherwise =
        delimit(() => transform(expr.otherwise), otherwiseStatements)
          ..parent = expr;
    final otherwiseAwait = seenAwait;

    // Only one side of this branch will get executed at a time, so just make
    // sure we have enough temps for either, not both at the same time.
    if (thenNameIndex > nameIndex) {
      nameIndex = thenNameIndex;
    }

    if (thenStatements.isEmpty && otherwiseStatements.isEmpty) {
      // Easy case: neither then nor otherwise emitted any statements.
      seenAwait = shouldName;
      return transformTreeNode(expr, () {
        expr.condition = transform(expr.condition)..parent = expr;
        seenAwait = seenAwait || thenAwait || otherwiseAwait;
      });
    }

    // If `then` or `otherwise` has emitted statements we will produce a
    // temporary t and emit:
    //
    // if ([condition]) {
    //   t = [left];
    // } else {
    //   t = [right];
    // }
    final result = allocateTemporary(nameIndex, expr.staticType);
    final thenBody = blockOf(thenStatements);
    final otherwiseBody = blockOf(otherwiseStatements);
    thenBody.addStatement(ExpressionStatement(VariableSet(result, expr.then)));
    otherwiseBody
        .addStatement(ExpressionStatement(VariableSet(result, expr.otherwise)));
    final branch = IfStatement(expr.condition, thenBody, otherwiseBody);
    statements.add(branch);

    seenAwait = false;
    branch.condition = transform(branch.condition)..parent = branch;

    nameIndex += 1;
    seenAwait = seenAwait || thenAwait || otherwiseAwait;
    return castVariableGet(result, expr.staticType);
  }

  // Await expression

  @override
  TreeNode visitAwaitExpression(AwaitExpression expr) {
    // TODO (omersa): Only name if the await is not already in assignment RHS
    return transformTreeNode(expr, () {
      expr.transformChildren(this);
    }, alwaysName: true);
  }

  // Block expressions

  @override
  TreeNode visitBlockExpression(BlockExpression expr) {
    return transformTreeNode(expr, () {
      expr.value = transform(expr.value)..parent = expr;
      final List<Statement> body = <Statement>[];
      for (final Statement stmt in expr.body.statements.reversed) {
        final Statement? translation = _rewriteStatement(stmt);
        if (translation != null) {
          body.add(translation);
        }
      }
      expr.body = Block(body.reversed.toList())..parent = expr;
    });
  }

  @override
  TreeNode visitLet(Let expr) {
    final body = transform(expr.body);
    final VariableDeclaration variable = expr.variable;
    if (seenAwait) {
      // There is an await in the body of `let var x = initializer in body` or
      // to its right.  We will produce the sequence of statements:
      //
      // <initializer's statements>
      // var x = <initializer's value>
      // <body's statements>
      //
      // and return the body's value.
      statements.add(variable);
      var index = nameIndex;
      seenAwait = false;
      variable.initializer = transform(variable.initializer!)
        ..parent = variable;
      // Temporaries used in the initializer or the body are not live but the
      // temporary used for the body is.
      if (index + 1 > nameIndex) {
        nameIndex = index + 1;
      }
      seenAwait = true;
      return body;
    } else {
      // The body in `let x = initializer in body` did not contain an await.
      // We can leave a let expression.
      return transformTreeNode(expr, () {
        // The body has already been translated.
        expr.body = body..parent = expr;
        variable.initializer = transform(variable.initializer!)
          ..parent = variable;
      });
    }
  }

  @override
  TreeNode visitFunctionNode(FunctionNode node) {
    var nestedRewriter = _AwaitTransformer(staticTypeContext, coreTypes);
    return nestedRewriter.transform(node);
  }

  /// This method translates a statement nested in an expression (e.g., in a
  /// block expression). It produces a translated statement, a list of
  /// statements which are side effects necessary for any await, and a flag
  /// indicating whether there was an await in the statement or to its right.
  /// The translated statement can be null in the case where there was already
  /// an await to the right.
  Statement? _rewriteStatement(Statement stmt) {
    // The translation is accumulating two lists of statements, an inner list
    // which is a reversed list of effects needed for the current expression
    // and an outer list which represents the block containing the current
    // statement. We need to preserve both of those from side effects.
    final List<Statement> savedInner = statements;
    final List<Statement> savedOuter = _statementTransformer.statements;
    statements = <Statement>[];
    _statementTransformer.statements = <Statement>[];
    stmt = _statementTransformer.transform(stmt);

    final List<Statement> results = _statementTransformer.statements;
    results.add(stmt);

    statements = savedInner;
    _statementTransformer.statements = savedOuter;
    if (!seenAwait && results.length == 1) {
      return results.first;
    }
    statements.addAll(results.reversed);
    return null;
  }

  @override
  TreeNode defaultStatement(Statement stmt) {
    throw UnsupportedError(
        "Use _rewriteStatement to transform statement: $stmt");
  }
}
