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

#include "vm/ast_transformer.h"

#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/thread.h"

namespace dart {

// Quick access to the current thread.
#define T (thread())

// Quick access to the current zone.
#define Z (thread()->zone())

// Quick synthetic token position.
#define ST(token_pos) ((token_pos).ToSynthetic())

// Nodes that are unreachable from already parsed expressions.
#define FOR_EACH_UNREACHABLE_NODE(V)                                           \
  V(AwaitMarker)                                                               \
  V(Case)                                                                      \
  V(CatchClause)                                                               \
  V(CloneContext)                                                              \
  V(ClosureCall)                                                               \
  V(DoWhile)                                                                   \
  V(If)                                                                        \
  V(InitStaticField)                                                           \
  V(InlinedFinally)                                                            \
  V(For)                                                                       \
  V(Jump)                                                                      \
  V(Stop)                                                                      \
  V(LoadInstanceField)                                                         \
  V(NativeBody)                                                                \
  V(Primary)                                                                   \
  V(Return)                                                                    \
  V(Sequence)                                                                  \
  V(StoreInstanceField)                                                        \
  V(Switch)                                                                    \
  V(TryCatch)                                                                  \
  V(While)

#define DEFINE_UNREACHABLE(BaseName)                                           \
  void AwaitTransformer::Visit##BaseName##Node(BaseName##Node* node) {         \
    UNREACHABLE();                                                             \
  }

FOR_EACH_UNREACHABLE_NODE(DEFINE_UNREACHABLE)
#undef DEFINE_UNREACHABLE

AwaitTransformer::AwaitTransformer(SequenceNode* preamble,
                                   LocalScope* async_temp_scope)
    : preamble_(preamble),
      temp_cnt_(0),
      async_temp_scope_(async_temp_scope),
      thread_(Thread::Current()) {
  ASSERT(async_temp_scope_ != NULL);
}


AstNode* AwaitTransformer::Transform(AstNode* expr) {
  expr->Visit(this);
  return result_;
}


LocalVariable* AwaitTransformer::EnsureCurrentTempVar() {
  String& symbol =
      String::ZoneHandle(Z, Symbols::NewFormatted(T, "%d", temp_cnt_));
  symbol = Symbols::FromConcat(T, Symbols::AwaitTempVarPrefix(), symbol);
  ASSERT(!symbol.IsNull());
  // Look up the variable in the scope used for async temp variables.
  LocalVariable* await_tmp = async_temp_scope_->LocalLookupVariable(symbol);
  if (await_tmp == NULL) {
    // We need a new temp variable; add it to the function's top scope.
    await_tmp = new (Z)
        LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                      symbol, Object::dynamic_type());
    async_temp_scope_->AddVariable(await_tmp);
    // After adding it to the top scope, we can look it up from the preamble.
    // The following call includes an ASSERT check.
    await_tmp = GetVariableInScope(preamble_->scope(), symbol);
  }
  return await_tmp;
}


LocalVariable* AwaitTransformer::GetVariableInScope(LocalScope* scope,
                                                    const String& symbol) {
  LocalVariable* var = scope->LookupVariable(symbol, false);
  ASSERT(var != NULL);
  return var;
}


LocalVariable* AwaitTransformer::AddNewTempVarToPreamble(
    AstNode* node,
    TokenPosition token_pos) {
  LocalVariable* tmp_var = EnsureCurrentTempVar();
  ASSERT(token_pos.IsSynthetic() || token_pos.IsNoSource());
  preamble_->Add(new (Z) StoreLocalNode(token_pos, tmp_var, node));
  NextTempVar();
  return tmp_var;
}


LoadLocalNode* AwaitTransformer::MakeName(AstNode* node) {
  LocalVariable* temp = AddNewTempVarToPreamble(node, ST(node->token_pos()));
  return new (Z) LoadLocalNode(ST(node->token_pos()), temp);
}


void AwaitTransformer::VisitLiteralNode(LiteralNode* node) {
  result_ = node;
}


void AwaitTransformer::VisitTypeNode(TypeNode* node) {
  result_ = new (Z) TypeNode(node->token_pos(), node->type());
}


void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
  // Await transformation:
  //
  //   :await_temp_var_X = <expr>;
  //   AwaitMarker(kNewContinuationState);
  //   :result_param = _awaitHelper(
  //      :await_temp_var_X, :async_then_callback, :async_catch_error_callback);
  //   return;  // (return_type() == kContinuationTarget)
  //
  //   :saved_try_ctx_var = :await_saved_try_ctx_var_y;
  //   :await_temp_var_(X+1) = :result_param;

  const TokenPosition token_pos = ST(node->token_pos());
  LocalVariable* async_op =
      GetVariableInScope(preamble_->scope(), Symbols::AsyncOperation());
  LocalVariable* async_then_callback =
      GetVariableInScope(preamble_->scope(), Symbols::AsyncThenCallback());
  LocalVariable* async_catch_error_callback = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncCatchErrorCallback());
  LocalVariable* result_param =
      GetVariableInScope(preamble_->scope(), Symbols::AsyncOperationParam());
  LocalVariable* error_param = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncOperationErrorParam());
  LocalVariable* stack_trace_param = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncOperationStackTraceParam());

  AstNode* transformed_expr = Transform(node->expr());
  LocalVariable* await_temp =
      AddNewTempVarToPreamble(transformed_expr, ST(node->token_pos()));

  AwaitMarkerNode* await_marker =
      new (Z) AwaitMarkerNode(async_temp_scope_, node->scope(), token_pos);
  preamble_->Add(await_marker);

  // :result_param = _awaitHelper(
  //      :await_temp, :async_then_callback, :async_catch_error_callback)
  const Library& async_lib = Library::Handle(Library::AsyncLibrary());
  const Function& async_await_helper = Function::ZoneHandle(
      Z, async_lib.LookupFunctionAllowPrivate(Symbols::AsyncAwaitHelper()));
  ASSERT(!async_await_helper.IsNull());
  ArgumentListNode* async_await_helper_args =
      new (Z) ArgumentListNode(token_pos);
  async_await_helper_args->Add(new (Z) LoadLocalNode(token_pos, await_temp));
  async_await_helper_args->Add(
      new (Z) LoadLocalNode(token_pos, async_then_callback));
  async_await_helper_args->Add(
      new (Z) LoadLocalNode(token_pos, async_catch_error_callback));
  StaticCallNode* await_helper_call = new (Z) StaticCallNode(
      node->token_pos(), async_await_helper, async_await_helper_args);

  preamble_->Add(
      new (Z) StoreLocalNode(token_pos, result_param, await_helper_call));

  ReturnNode* continuation_return = new (Z) ReturnNode(token_pos);
  continuation_return->set_return_type(ReturnNode::kContinuationTarget);
  preamble_->Add(continuation_return);

  // If this expression is part of a try block, also append the code for
  // restoring the saved try context that lives on the stack and possibly the
  // saved try context of the outer try block.
  if (node->saved_try_ctx() != NULL) {
    preamble_->Add(new (Z) StoreLocalNode(
        token_pos, node->saved_try_ctx(),
        new (Z) LoadLocalNode(token_pos, node->async_saved_try_ctx())));
    if (node->outer_saved_try_ctx() != NULL) {
      preamble_->Add(new (Z) StoreLocalNode(
          token_pos, node->outer_saved_try_ctx(),
          new (Z) LoadLocalNode(token_pos, node->outer_async_saved_try_ctx())));
    }
  } else {
    ASSERT(node->outer_saved_try_ctx() == NULL);
  }

  // Load the async_op variable. It is unused, but the observatory uses it
  // to determine if a breakpoint is inside an asynchronous function.
  LoadLocalNode* load_async_op = new (Z) LoadLocalNode(token_pos, async_op);
  preamble_->Add(load_async_op);

  LoadLocalNode* load_error_param =
      new (Z) LoadLocalNode(token_pos, error_param);
  LoadLocalNode* load_stack_trace_param =
      new (Z) LoadLocalNode(token_pos, stack_trace_param);
  SequenceNode* error_ne_null_branch =
      new (Z) SequenceNode(token_pos, ChainNewScope(preamble_->scope()));
  error_ne_null_branch->Add(
      new (Z) ThrowNode(token_pos, load_error_param, load_stack_trace_param));
  preamble_->Add(new (Z) IfNode(
      token_pos, new (Z) ComparisonNode(
                     token_pos, Token::kNE, load_error_param,
                     new (Z) LiteralNode(token_pos, Object::null_instance())),
      error_ne_null_branch, NULL));

  result_ = MakeName(new (Z) LoadLocalNode(token_pos, result_param));
}


// Transforms boolean expressions into a sequence of evaluatons that only lazily
// evaluate subexpressions.
//
// Example:
//
//   (a || b) only evaluates b if a is false
//
// Transformation (roughly):
//
//   t_1 = a;
//   if (!t_1) {
//     t_2 = b;
//   }
//   t_3 = t_1 || t_2;  // Compiler takes care that lazy evaluation takes place
//                         on this level.
AstNode* AwaitTransformer::LazyTransform(const Token::Kind logical_op,
                                         AstNode* new_left,
                                         AstNode* right) {
  ASSERT(logical_op == Token::kAND || logical_op == Token::kOR);
  AstNode* result = NULL;
  const Token::Kind compare_logical_op =
      (logical_op == Token::kAND) ? Token::kEQ : Token::kNE;
  SequenceNode* eval = new (Z) SequenceNode(ST(new_left->token_pos()),
                                            ChainNewScope(preamble_->scope()));
  SequenceNode* saved_preamble = preamble_;
  preamble_ = eval;
  result = Transform(right);
  preamble_ = saved_preamble;
  IfNode* right_body = new (Z)
      IfNode(ST(new_left->token_pos()),
             new (Z) ComparisonNode(
                 ST(new_left->token_pos()), compare_logical_op, new_left,
                 new (Z) LiteralNode(ST(new_left->token_pos()), Bool::True())),
             eval, NULL);
  preamble_->Add(right_body);
  return result;
}


LocalScope* AwaitTransformer::ChainNewScope(LocalScope* parent) {
  return new (Z)
      LocalScope(parent, parent->function_level(), parent->loop_level());
}


void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) {
  AstNode* new_left = Transform(node->left());
  AstNode* new_right = NULL;
  // Preserve lazy evaluaton.
  if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
    new_right = LazyTransform(node->kind(), new_left, node->right());
  } else {
    new_right = Transform(node->right());
  }
  result_ = MakeName(new (Z) BinaryOpNode(node->token_pos(), node->kind(),
                                          new_left, new_right));
}


void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) {
  AstNode* new_left = Transform(node->left());
  AstNode* new_right = Transform(node->right());
  result_ = MakeName(new (Z) ComparisonNode(node->token_pos(), node->kind(),
                                            new_left, new_right));
}


void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) {
  AstNode* new_operand = Transform(node->operand());
  result_ = MakeName(
      new (Z) UnaryOpNode(node->token_pos(), node->kind(), new_operand));
}


// ::= (<condition>) ? <true-branch> : <false-branch>
//
void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) {
  AstNode* new_condition = Transform(node->condition());
  SequenceNode* new_true = new (Z) SequenceNode(
      ST(node->true_expr()->token_pos()), ChainNewScope(preamble_->scope()));
  SequenceNode* saved_preamble = preamble_;
  preamble_ = new_true;
  AstNode* new_true_result = Transform(node->true_expr());
  SequenceNode* new_false = new (Z) SequenceNode(
      ST(node->false_expr()->token_pos()), ChainNewScope(preamble_->scope()));
  preamble_ = new_false;
  AstNode* new_false_result = Transform(node->false_expr());
  preamble_ = saved_preamble;
  IfNode* new_if =
      new (Z) IfNode(ST(node->token_pos()), new_condition, new_true, new_false);
  preamble_->Add(new_if);
  result_ = MakeName(new (Z) ConditionalExprNode(
      ST(node->token_pos()), new_condition, new_true_result, new_false_result));
}


void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) {
  ArgumentListNode* new_args = new (Z) ArgumentListNode(node->token_pos());
  for (intptr_t i = 0; i < node->length(); i++) {
    new_args->Add(Transform(node->NodeAt(i)));
  }
  new_args->set_names(node->names());
  result_ = new_args;
}


void AwaitTransformer::VisitArrayNode(ArrayNode* node) {
  GrowableArray<AstNode*> new_elements;
  for (intptr_t i = 0; i < node->length(); i++) {
    new_elements.Add(Transform(node->ElementAt(i)));
  }
  result_ = new (Z) ArrayNode(node->token_pos(), node->type(), new_elements);
}


void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) {
  ArrayNode* new_value = Transform(node->value())->AsArrayNode();
  result_ =
      MakeName(new (Z) StringInterpolateNode(node->token_pos(), new_value));
}


void AwaitTransformer::VisitClosureNode(ClosureNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  result_ = MakeName(new (Z) ClosureNode(node->token_pos(), node->function(),
                                         new_receiver, node->scope()));
}


void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) {
  AstNode* new_receiver = Transform(node->receiver());
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  result_ = MakeName(new (Z) InstanceCallNode(node->token_pos(), new_receiver,
                                              node->function_name(), new_args,
                                              node->is_conditional()));
}


void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) {
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  result_ = MakeName(
      new (Z) StaticCallNode(node->token_pos(), node->function(), new_args));
}


void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) {
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  result_ = MakeName(
      new (Z) ConstructorCallNode(node->token_pos(), node->type_arguments(),
                                  node->constructor(), new_args));
}


void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) {
  AstNode* new_receiver = Transform(node->receiver());
  result_ = MakeName(new (Z) InstanceGetterNode(node->token_pos(), new_receiver,
                                                node->field_name(),
                                                node->is_conditional()));
}


void AwaitTransformer::VisitInstanceSetterNode(InstanceSetterNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  AstNode* new_value = Transform(node->value());
  result_ = MakeName(new (Z) InstanceSetterNode(node->token_pos(), new_receiver,
                                                node->field_name(), new_value,
                                                node->is_conditional()));
}


void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  StaticGetterNode* new_getter = new (Z) StaticGetterNode(
      node->token_pos(), new_receiver, node->cls(), node->field_name());
  new_getter->set_owner(node->owner());
  result_ = MakeName(new_getter);
}


void AwaitTransformer::VisitStaticSetterNode(StaticSetterNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  AstNode* new_value = Transform(node->value());
  StaticSetterNode* new_setter =
      node->function().IsNull()
          ? new (Z) StaticSetterNode(node->token_pos(), new_receiver,
                                     node->cls(), node->field_name(), new_value)
          : new (Z) StaticSetterNode(node->token_pos(), new_receiver,
                                     node->field_name(), node->function(),
                                     new_value);

  result_ = MakeName(new_setter);
}


void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) {
  result_ = MakeName(node);
}


void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) {
  AstNode* new_value = Transform(node->value());
  result_ = MakeName(
      new (Z) StoreLocalNode(node->token_pos(), &node->local(), new_value));
}


void AwaitTransformer::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
  result_ = MakeName(node);
}


void AwaitTransformer::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
  AstNode* new_value = Transform(node->value());
  result_ = MakeName(new (Z) StoreStaticFieldNode(
      node->token_pos(), Field::ZoneHandle(Z, node->field().Original()),
      new_value));
}


void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) {
  AstNode* new_array = Transform(node->array());
  AstNode* new_index = Transform(node->index_expr());
  result_ = MakeName(new (Z) LoadIndexedNode(node->token_pos(), new_array,
                                             new_index, node->super_class()));
}


void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) {
  AstNode* new_array = Transform(node->array());
  AstNode* new_index = Transform(node->index_expr());
  AstNode* new_value = Transform(node->value());
  result_ = MakeName(new (Z) StoreIndexedNode(
      node->token_pos(), new_array, new_index, new_value, node->super_class()));
}


void AwaitTransformer::VisitAssignableNode(AssignableNode* node) {
  AstNode* new_expr = Transform(node->expr());
  result_ = MakeName(new (Z) AssignableNode(node->token_pos(), new_expr,
                                            node->type(), node->dst_name()));
}


void AwaitTransformer::VisitLetNode(LetNode* node) {
  // Add all the initializer nodes to the preamble and the
  // temporary variables to the scope for async temporary variables.
  // The temporary variables will be captured as a side effect of being
  // added to a scope, and the subsequent nodes that are added to the
  // preample can access them.
  for (intptr_t i = 0; i < node->num_temps(); i++) {
    async_temp_scope_->AddVariable(node->TempAt(i));
    AstNode* new_init_val = Transform(node->InitializerAt(i));
    preamble_->Add(new (Z) StoreLocalNode(node->token_pos(), node->TempAt(i),
                                          new_init_val));
  }

  // Add all expressions but the last to the preamble. We must do
  // this because subexpressions of the awaitable expression we
  // are currently transforming may depend on each other,
  // e.g. await foo(a++, a++). Thus we must preserve the order of the
  // transformed subexpressions.
  for (intptr_t i = 0; i < node->nodes().length() - 1; i++) {
    preamble_->Add(Transform(node->nodes()[i]));
  }

  // The last expression in the let node is the value of the node.
  // The result of the transformed let node is this expression.
  ASSERT(node->nodes().length() > 0);
  const intptr_t last_node_index = node->nodes().length() - 1;
  result_ = Transform(node->nodes()[last_node_index]);
}


void AwaitTransformer::VisitThrowNode(ThrowNode* node) {
  AstNode* new_exception = Transform(node->exception());
  result_ = MakeName(
      new (Z) ThrowNode(node->token_pos(), new_exception, node->stacktrace()));
}

}  // namespace dart
