// 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/parser.h"

namespace dart {

// Quick access to the locally defined isolate() method.
#define I (isolate())

// 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(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,
                                   const Library& library,
                                   ParsedFunction* const parsed_function,
                                   LocalScope* function_top)
    : preamble_(preamble),
      temp_cnt_(0),
      library_(library),
      parsed_function_(parsed_function),
      function_top_(function_top),
      isolate_(Isolate::Current()) {
  ASSERT(function_top_ != NULL);
}


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


LocalVariable* AwaitTransformer::EnsureCurrentTempVar() {
  const char* await_temp_prefix = ":await_temp_var_";
  const String& cnt_str = String::ZoneHandle(
      I, String::NewFormatted("%s%d", await_temp_prefix, temp_cnt_));
  const String& symbol = String::ZoneHandle(I, Symbols::New(cnt_str));
  ASSERT(!symbol.IsNull());
  // Look up the variable through the preamble scope.
  LocalVariable* await_tmp = preamble_->scope()->LookupVariable(symbol, false);
  if (await_tmp == NULL) {
    // If we need a new temp variable, we add it to the function's top scope.
    await_tmp = new (I) LocalVariable(
        Scanner::kNoSourcePos, symbol, Type::ZoneHandle(Type::DynamicType()));
    function_top_->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::AddToPreambleNewTempVar(AstNode* node) {
  LocalVariable* tmp_var = EnsureCurrentTempVar();
  preamble_->Add(new(I) StoreLocalNode(Scanner::kNoSourcePos, tmp_var, node));
  NextTempVar();
  return tmp_var;
}


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


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


void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
  // Await transformation:
  //
  //   :await_temp_var_X = <expr>;
  //   :result_param = :await_temp_var_X;
  //   if (:result_param is Future) {
  //     AwaitMarker(kNewContinuationState);
  //     :result_param = :result_param.then(:async_op);
  //     _asyncCatchHelper(:result_param.catchError, :async_op);
  //     return;  // (return_type() == kContinuation)
  //   }
  //   AwaitMarker(kTargetForContinuation);  // Join happens here.
  //   :saved_try_ctx_var = :await_saved_try_ctx_var_y;
  //   :await_temp_var_(X+1) = :result_param;

  LocalVariable* async_op = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncOperation());
  LocalVariable* result_param = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncOperationParam());
  LocalVariable* error_param = GetVariableInScope(
      preamble_->scope(), Symbols::AsyncOperationErrorParam());

  node->expr()->Visit(this);
  preamble_->Add(new(I) StoreLocalNode(
      Scanner::kNoSourcePos, result_param, result_));
  LoadLocalNode* load_result_param = new(I) LoadLocalNode(
      Scanner::kNoSourcePos, result_param);
  LocalScope* is_future_scope = ChainNewScope(preamble_->scope());
  SequenceNode* is_future_branch = new (I) SequenceNode(
      Scanner::kNoSourcePos, is_future_scope);
  AwaitMarkerNode* await_marker = new (I) AwaitMarkerNode(
      AwaitMarkerNode::kNewContinuationState);
  await_marker->set_scope(is_future_scope);
  GetVariableInScope(is_future_scope, Symbols::AwaitJumpVar());
  GetVariableInScope(is_future_scope, Symbols::AwaitContextVar());
  is_future_branch->Add(await_marker);
  ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos);
  args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op));
  is_future_branch->Add(new (I) StoreLocalNode(
      Scanner::kNoSourcePos,
      result_param,
      new(I) InstanceCallNode(
          Scanner::kNoSourcePos,
          load_result_param,
          Symbols::FutureThen(),
          args)));
  const Library& core_lib = Library::Handle(Library::CoreLibrary());
  const Function& async_catch_helper = Function::ZoneHandle(
      I, core_lib.LookupFunctionAllowPrivate(Symbols::AsyncCatchHelper()));
  ASSERT(!async_catch_helper.IsNull());
  ArgumentListNode* catch_helper_args = new (I) ArgumentListNode(
      Scanner::kNoSourcePos);
  InstanceGetterNode* catch_error_getter = new (I) InstanceGetterNode(
      Scanner::kNoSourcePos,
      load_result_param,
      Symbols::FutureCatchError());
  catch_helper_args->Add(catch_error_getter);
  catch_helper_args->Add(new (I) LoadLocalNode(
      Scanner::kNoSourcePos, async_op));
  is_future_branch->Add(new (I) StaticCallNode(
      Scanner::kNoSourcePos,
      async_catch_helper,
      catch_helper_args));
  ReturnNode* continuation_return = new(I) ReturnNode(Scanner::kNoSourcePos);
  continuation_return->set_return_type(ReturnNode::kContinuation);
  is_future_branch->Add(continuation_return);

  const Class& cls = Class::ZoneHandle(
      I, library_.LookupClass(Symbols::Future()));
  const AbstractType& future_type = AbstractType::ZoneHandle(I, cls.RareType());
  ASSERT(!future_type.IsNull());
  preamble_->Add(new(I) IfNode(
      Scanner::kNoSourcePos,
      new (I) ComparisonNode(
          Scanner::kNoSourcePos,
          Token::kIS,
          load_result_param,
          new (I) TypeNode(Scanner::kNoSourcePos, future_type)),
      is_future_branch,
      NULL));
  preamble_->Add(new (I) AwaitMarkerNode(
      AwaitMarkerNode::kTargetForContinuation));

  // If this expression is part of a try block, also append the code for
  // restoring the saved try context that lives on the stack.
  const String& async_saved_try_ctx_name =
      String::Handle(I, parsed_function_->async_saved_try_ctx_name());
  if (!async_saved_try_ctx_name.IsNull()) {
    LocalVariable* async_saved_try_ctx =
        GetVariableInScope(preamble_->scope(), async_saved_try_ctx_name);
    preamble_->Add(new (I) StoreLocalNode(
        Scanner::kNoSourcePos,
        parsed_function_->saved_try_ctx(),
        new (I) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
  }

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

  LocalVariable* result = AddToPreambleNewTempVar(new(I) LoadLocalNode(
      Scanner::kNoSourcePos, result_param));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


// 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 (I) SequenceNode(
      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
  SequenceNode* saved_preamble = preamble_;
  preamble_ = eval;
  result = Transform(right);
  preamble_ = saved_preamble;
  IfNode* right_body = new(I) IfNode(
      Scanner::kNoSourcePos,
      new(I) ComparisonNode(
          Scanner::kNoSourcePos,
          compare_logical_op,
          new_left,
          new(I) LiteralNode(Scanner::kNoSourcePos, Bool::True())),
      eval,
      NULL);
  preamble_->Add(right_body);
  return result;
}


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


void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) {
  node->left()->Visit(this);
  AstNode* new_left = result_;
  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());
  }
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) BinaryOpNode(node->token_pos(),
                          node->kind(),
                          new_left,
                          new_right));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitBinaryOpWithMask32Node(
    BinaryOpWithMask32Node* node) {
  node->left()->Visit(this);
  AstNode* new_left = result_;
  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());
  }
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) BinaryOpWithMask32Node(node->token_pos(),
                                    node->kind(),
                                    new_left,
                                    new_right,
                                    node->mask32()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) {
  AstNode* new_left = Transform(node->left());
  AstNode* new_right = Transform(node->right());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) ComparisonNode(node->token_pos(),
                            node->kind(),
                            new_left,
                            new_right));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) {
  AstNode* new_operand = Transform(node->operand());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) UnaryOpNode(node->token_pos(), node->kind(), new_operand));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


// ::= (<condition>) ? <true-branch> : <false-branch>
//
void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) {
  AstNode* new_condition = Transform(node->condition());
  SequenceNode* new_true = new (I) SequenceNode(
      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
  SequenceNode* saved_preamble = preamble_;
  preamble_ = new_true;
  AstNode* new_true_result = Transform(node->true_expr());
  SequenceNode* new_false = new (I) SequenceNode(
      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
  preamble_ = new_false;
  AstNode* new_false_result = Transform(node->false_expr());
  preamble_ = saved_preamble;
  IfNode* new_if = new(I) IfNode(Scanner::kNoSourcePos,
                                 new_condition,
                                 new_true,
                                 new_false);
  preamble_->Add(new_if);
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) ConditionalExprNode(Scanner::kNoSourcePos,
                                 new_condition,
                                 new_true_result,
                                 new_false_result));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) {
  ArgumentListNode* new_args = new(I) ArgumentListNode(node->token_pos());
  for (intptr_t i = 0; i < node->length(); i++) {
    new_args->Add(Transform(node->NodeAt(i)));
  }
  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(I) ArrayNode(node->token_pos(), node->type(), new_elements);
}


void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) {
  ArrayNode* new_value = Transform(node->value())->AsArrayNode();
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StringInterpolateNode(node->token_pos(),
                                   new_value));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitClosureNode(ClosureNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) ClosureNode(node->token_pos(),
                         node->function(),
                         new_receiver,
                         node->scope()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) {
  AstNode* new_receiver = Transform(node->receiver());
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) InstanceCallNode(node->token_pos(),
                              new_receiver,
                              node->function_name(),
                              new_args));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) {
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StaticCallNode(node->token_pos(),
                            node->function(),
                            new_args));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) {
  ArgumentListNode* new_args =
      Transform(node->arguments())->AsArgumentListNode();
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) ConstructorCallNode(node->token_pos(),
                                 node->type_arguments(),
                                 node->constructor(),
                                 new_args));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) {
  AstNode* new_receiver = Transform(node->receiver());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) InstanceGetterNode(node->token_pos(),
                                new_receiver,
                                node->field_name()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


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());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) InstanceSetterNode(node->token_pos(),
                                new_receiver,
                                node->field_name(),
                                new_value));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) {
  AstNode* new_receiver = node->receiver();
  if (new_receiver != NULL) {
    new_receiver = Transform(new_receiver);
  }
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StaticGetterNode(node->token_pos(),
                              new_receiver,
                              node->is_super_getter(),
                              node->cls(),
                              node->field_name()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


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());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StaticSetterNode(node->token_pos(),
                              new_receiver,
                              node->cls(),
                              node->field_name(),
                              new_value));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) {
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) LoadLocalNode(node->token_pos(), &node->local()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) {
  AstNode* new_value = Transform(node->value());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StoreLocalNode(node->token_pos(),
                            &node->local(),
                            new_value));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) LoadStaticFieldNode(node->token_pos(),
                                 node->field()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
  AstNode* new_value = Transform(node->value());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StoreStaticFieldNode(node->token_pos(),
                                  node->field(),
                                  new_value));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) {
  AstNode* new_array = Transform(node->array());
  AstNode* new_index = Transform(node->index_expr());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) LoadIndexedNode(node->token_pos(),
                             new_array,
                             new_index,
                             node->super_class()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) {
  AstNode* new_array = Transform(node->array());
  AstNode* new_index = Transform(node->index_expr());
  AstNode* new_value = Transform(node->value());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) StoreIndexedNode(node->token_pos(),
                              new_array,
                              new_index,
                              new_value,
                              node->super_class()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitAssignableNode(AssignableNode* node) {
  AstNode* new_expr = Transform(node->expr());
  LocalVariable* result = AddToPreambleNewTempVar(
      new(I) AssignableNode(node->token_pos(),
                            new_expr,
                            node->type(),
                            node->dst_name()));
  result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
}


void AwaitTransformer::VisitLetNode(LetNode* node) {
  // TODO(mlippautz): Check initializers and their temps.
  LetNode* result = new(I) LetNode(node->token_pos());
  for (intptr_t i = 0; i < node->nodes().length(); i++) {
    result->AddNode(Transform(node->nodes()[i]));
  }
  result_ = result;
}


void AwaitTransformer::VisitThrowNode(ThrowNode* node) {
  // TODO(mlippautz): Check if relevant.
  AstNode* new_exception = Transform(node->exception());
  AstNode* new_stacktrace = Transform(node->stacktrace());
  result_ = new(I) ThrowNode(node->token_pos(),
                             new_exception,
                             new_stacktrace);
}

}  // namespace dart
