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

library kernel.transformations.async;

import '../kernel.dart';
import '../type_environment.dart';
import 'continuation.dart';

/// A transformer that introduces temporary variables for all subexpressions
/// that are alive across yield points (AwaitExpression).
///
/// The transformer is invoked by passing [rewrite] a top-level expression.
///
/// All intermediate values that are possible live across an await are named in
/// local variables.
///
/// Await expressions are translated into a call to a helper function and a
/// native yield.
class ExpressionLifter extends Transformer {
  final AsyncRewriterBase continuationRewriter;

  /// Have we 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;

  final VariableDeclaration asyncResult = new VariableDeclaration(':result');
  final List<VariableDeclaration> variables = <VariableDeclaration>[];

  ExpressionLifter(this.continuationRewriter);

  StatefulStaticTypeContext get _staticTypeContext =>
      continuationRewriter.staticTypeContext;

  Block blockOf(List<Statement> statements) {
    return new Block(statements.reversed.toList());
  }

  /// Rewrite a toplevel expression (toplevel wrt. a statement).
  ///
  /// 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.
  Expression rewrite(Expression expression, List<Statement> outer) {
    assert(statements.isEmpty);
    var saved = seenAwait;
    seenAwait = false;
    Expression result = transform(expression);
    outer.addAll(statements.reversed);
    statements.clear();
    seenAwait = seenAwait || saved;
    return result;
  }

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

  // Name an expression by emitting an assignment to a temporary variable.
  Expression name(Expression expr) {
    // Allocate as dynamic as temps might be reused with different types.
    VariableDeclaration temp =
        allocateTemporary(nameIndex, const DynamicType());
    statements.add(ExpressionStatement(VariableSet(temp, expr)));
    // Type annotate the get via an unsafe cast since all temps are allocated
    // as dynamic.
    DartType type = expr.getStaticType(_staticTypeContext);
    return StaticInvocation(continuationRewriter.helper.unsafeCast,
        Arguments(<Expression>[VariableGet(temp)], types: <DartType>[type]));
  }

  VariableDeclaration allocateTemporary(int index,
      [DartType type = const DynamicType()]) {
    for (var i = variables.length; i <= index; i++) {
      variables.add(VariableDeclaration(":async_temporary_${i}", type: type));
    }
    return variables[index];
  }

  // Simple literals.  These are pure expressions so they can be evaluated after
  // an await to their right.
  TreeNode visitSymbolLiteral(SymbolLiteral expr) => expr;
  TreeNode visitTypeLiteral(TypeLiteral expr) => expr;
  TreeNode visitThisExpression(ThisExpression expr) => expr;
  TreeNode visitStringLiteral(StringLiteral expr) => expr;
  TreeNode visitIntLiteral(IntLiteral expr) => expr;
  TreeNode visitDoubleLiteral(DoubleLiteral expr) => expr;
  TreeNode visitBoolLiteral(BoolLiteral expr) => expr;
  TreeNode visitNullLiteral(NullLiteral expr) => expr;

  // Nullary expressions with effects.
  Expression nullary(Expression expr) {
    if (seenAwait) {
      expr = name(expr);
      ++nameIndex;
    }
    return expr;
  }

  TreeNode visitInvalidExpression(InvalidExpression expr) => nullary(expr);
  TreeNode visitSuperPropertyGet(SuperPropertyGet expr) => nullary(expr);
  TreeNode visitStaticGet(StaticGet expr) => nullary(expr);
  TreeNode visitStaticTearOff(StaticTearOff expr) => nullary(expr);
  TreeNode visitRethrow(Rethrow expr) => nullary(expr);

  // Getting a final or const variable is not an effect so it can be evaluated
  // after an await to its right.
  TreeNode visitVariableGet(VariableGet expr) {
    Expression result = expr;
    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 action()) {
    var shouldName = seenAwait;

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

    // 2. Remember the number of live temporaries before transforming the
    // children.
    var 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;
  }

  // Unary expressions.
  Expression unary(Expression expr) {
    return transformTreeNode(expr, () {
      expr.transformChildren(this);
    });
  }

  @override
  TreeNode visitVariableSet(VariableSet expr) => unary(expr);
  @override
  TreeNode visitPropertyGet(PropertyGet 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 visitFunctionTearOff(FunctionTearOff 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 visitPropertySet(PropertySet expr) {
    return transformTreeNode(expr, () {
      expr.value = transform(expr.value)..parent = expr;
      expr.receiver = transform(expr.receiver)..parent = 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;
    });
  }

  TreeNode visitArguments(Arguments args) {
    for (var named in args.named.reversed) {
      named.value = transform(named.value)..parent = named;
    }
    var positional = args.positional;
    for (var i = positional.length - 1; i >= 0; --i) {
      positional[i] = transform(positional[i])..parent = args;
    }
    // Returns the arguments, which is assumed at the call sites because they do
    // not replace the arguments or set parent pointers.
    return args;
  }

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

  @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 visitEqualsNull(EqualsNull expr) => unary(expr);

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

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

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

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

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

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

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

  // Control flow.
  TreeNode visitLogicalExpression(LogicalExpression expr) {
    var shouldName = seenAwait;

    // Right is delimited because it is conditionally evaluated.
    var rightStatements = <Statement>[];
    seenAwait = false;
    expr.right = delimit(() => transform(expr.right), rightStatements)
      ..parent = expr;
    var 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).
    var rightBody = blockOf(rightStatements);
    var result = allocateTemporary(
        nameIndex,
        _staticTypeContext.typeEnvironment.coreTypes
            .boolRawType(_staticTypeContext.nonNullable));
    rightBody.addStatement(new ExpressionStatement(new VariableSet(
        result,
        new MethodInvocation(expr.right, new Name('=='),
            new Arguments(<Expression>[new BoolLiteral(true)])))));
    var then, otherwise;
    if (expr.operatorEnum == LogicalExpressionOperator.AND) {
      then = rightBody;
      otherwise = null;
    } else {
      then = new EmptyStatement();
      otherwise = rightBody;
    }
    statements.add(new IfStatement(new VariableGet(result), then, otherwise));

    var test = new MethodInvocation(expr.left, new Name('=='),
        new Arguments(<Expression>[new BoolLiteral(true)]));
    statements.add(new ExpressionStatement(new VariableSet(result, test)));

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

    ++nameIndex;
    seenAwait = seenAwait || rightAwait;
    return new VariableGet(result);
  }

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

    final savedNameIndex = nameIndex;

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

    final thenNameIndex = nameIndex;
    nameIndex = savedNameIndex;

    var otherwiseStatements = <Statement>[];
    seenAwait = false;
    expr.otherwise =
        delimit(() => transform(expr.otherwise), otherwiseStatements)
          ..parent = expr;
    var 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];
    // }
    var result = allocateTemporary(nameIndex, expr.staticType);
    var thenBody = blockOf(thenStatements);
    var otherwiseBody = blockOf(otherwiseStatements);
    thenBody.addStatement(
        new ExpressionStatement(new VariableSet(result, expr.then)));
    otherwiseBody.addStatement(
        new ExpressionStatement(new VariableSet(result, expr.otherwise)));
    var branch = new IfStatement(expr.condition, thenBody, otherwiseBody);
    statements.add(branch);

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

    ++nameIndex;
    seenAwait = seenAwait || thenAwait || otherwiseAwait;
    return new VariableGet(result);
  }

  // Others.
  TreeNode visitAwaitExpression(AwaitExpression expr) {
    final R = continuationRewriter;
    var shouldName = seenAwait;
    var type = expr.getStaticType(_staticTypeContext);
    Expression result = new VariableGet(asyncResult);
    if (type is! DynamicType) {
      int fileOffset = expr.operand.fileOffset;
      if (fileOffset == TreeNode.noOffset) {
        fileOffset = expr.fileOffset;
      }
      assert(fileOffset != TreeNode.noOffset);
      result = new StaticInvocation(
          continuationRewriter.helper.unsafeCast,
          new Arguments(<Expression>[result], types: <DartType>[type])
            ..fileOffset = fileOffset)
        ..fileOffset = fileOffset;
    }

    // The statements are in reverse order, so name the result first if
    // necessary and then add the two other statements in reverse.
    if (shouldName) result = name(result);
    Arguments arguments = new Arguments(<Expression>[
      expr.operand,
      new VariableGet(R.thenContinuationVariable),
      new VariableGet(R.catchErrorContinuationVariable),
      new VariableGet(R.nestedClosureVariable),
    ]);

    // We are building
    //
    //     [yield] (let _ = _awaitHelper(...) in null)
    //
    // to ensure that :await_jump_var and :await_jump_ctx are updated
    // before _awaitHelper is invoked (see BuildYieldStatement in
    // StreamingFlowGraphBuilder for details of how [yield] is translated to
    // IL). This guarantees that recursive invocation of the current function
    // would continue from the correct "jump" position. Recursive invocations
    // arise if future we are awaiting completes synchronously. Builtin Future
    // implementation don't complete synchronously, but Flutter's
    // SynchronousFuture do (see bug http://dartbug.com/32098 for more details).
    statements.add(R.createContinuationPoint(new Let(
        new VariableDeclaration(null,
            initializer: new StaticInvocation(R.helper.awaitHelper, arguments)
              ..fileOffset = expr.fileOffset),
        new NullLiteral()))
      ..fileOffset = expr.fileOffset);

    seenAwait = false;
    var index = nameIndex;
    arguments.positional[0] = transform(expr.operand)..parent = arguments;

    if (shouldName && index + 1 > nameIndex) nameIndex = index + 1;
    seenAwait = true;
    return result;
  }

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

  TreeNode visitLet(Let expr) {
    var body = transform(expr.body);

    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.
      //
      // So x is in scope for all the body's statements and the body's value.
      // This has the unpleasant consequence that all let-bound variables with
      // await in the let's body will end up hoisted out of the expression and
      // allocated to the context in the VM, even if they have no uses
      // (`let _ = e0 in e1` can be used for sequencing of `e0` and `e1`).
      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;
      });
    }
  }

  visitFunctionNode(FunctionNode node) {
    var nestedRewriter = new RecursiveContinuationRewriter(
        continuationRewriter.helper, _staticTypeContext);
    return nestedRewriter.transform(node);
  }

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

  Statement? _rewriteStatement(Statement stmt) {
    // 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.

    // 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.
    List<Statement> savedInner = statements;
    List<Statement> savedOuter = continuationRewriter.statements;
    statements = <Statement>[];
    continuationRewriter.statements = <Statement>[];
    continuationRewriter.transform(stmt);

    List<Statement> results = continuationRewriter.statements;
    statements = savedInner;
    continuationRewriter.statements = savedOuter;
    if (!seenAwait && results.length == 1) return results.first;
    statements.addAll(results.reversed);
    return null;
  }

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