// Copyright (c) 2011, 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_printer.h"

#include "vm/handles.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/parser.h"

namespace dart {

AstPrinter::AstPrinter() { }


AstPrinter::~AstPrinter() { }


void AstPrinter::VisitGenericAstNode(AstNode* node) {
  OS::Print("(%s ", node->Name());
  node->VisitChildren(this);
  OS::Print(")");
}


void AstPrinter::VisitSequenceNode(SequenceNode* node_sequence) {
  // TODO(regis): Make the output more readable by indenting the nested
  // sequences. This could be achieved using a AstPrinterContext similar to the
  // CodeGeneratorContext.
  ASSERT(node_sequence != NULL);
  for (int i = 0; i < node_sequence->length(); i++) {
    OS::Print("scope %p: ",
              node_sequence->scope());
    node_sequence->NodeAt(i)->Visit(this);
    OS::Print("\n");
  }
}


void AstPrinter::VisitCloneContextNode(CloneContextNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitArgumentListNode(ArgumentListNode* arguments) {
  VisitGenericAstNode(arguments);
}


void AstPrinter::VisitArgumentDefinitionTestNode(
    ArgumentDefinitionTestNode* node) {
  OS::Print("(%s ?%s @%"Pd")",
            node->Name(),
            node->formal_parameter_name().ToCString(),
            node->formal_parameter_index());
}


void AstPrinter::VisitReturnNode(ReturnNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitGenericLocalNode(AstNode* node,
                                       const LocalVariable& var) {
  OS::Print("(%s %s%s '%s'",
            node->Name(),
            var.is_final() ? "final " : "",
            String::Handle(var.type().Name()).ToCString(),
            var.name().ToCString());
  if (var.HasIndex()) {
    OS::Print(" @%d", var.index());
    if (var.is_captured()) {
      OS::Print(" ctx %d", var.owner()->context_level());
    }
  }
  node->VisitChildren(this);
  OS::Print(")");
}


void AstPrinter::VisitLoadLocalNode(LoadLocalNode* node) {
  VisitGenericLocalNode(node, node->local());
}


void AstPrinter::VisitStoreLocalNode(StoreLocalNode* node) {
  VisitGenericLocalNode(node, node->local());
}


void AstPrinter::VisitGenericFieldNode(AstNode* node, const Field& field) {
  OS::Print("(%s %s%s '%s' ",
            node->Name(),
            field.is_final() ? "final " : "",
            String::Handle(AbstractType::Handle(field.type()).Name()).
                ToCString(),
            String::Handle(field.name()).ToCString());
  node->VisitChildren(this);
  OS::Print(")");
}


void AstPrinter::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) {
  VisitGenericFieldNode(node, node->field());
}


void AstPrinter::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) {
  VisitGenericFieldNode(node, node->field());
}


void AstPrinter::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
  VisitGenericFieldNode(node, node->field());
}


void AstPrinter::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
  VisitGenericFieldNode(node, node->field());
}


void AstPrinter::VisitLetNode(LetNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitArrayNode(ArrayNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitLiteralNode(LiteralNode* node) {
  const Instance& literal = node->literal();
  OS::Print("'%s'", literal.ToCString());
}


void AstPrinter::VisitTypeNode(TypeNode* node) {
  const AbstractType& type = node->type();
  OS::Print("'%s'", String::Handle(type.Name()).ToCString());
}


void AstPrinter::VisitAssignableNode(AssignableNode* node) {
  OS::Print("(assignable ");
  node->expr()->Visit(this);
  const AbstractType& type = node->type();
  const String& dst_name = node->dst_name();
  OS::Print(" to type '%s' of '%s')",
            String::Handle(type.Name()).ToCString(),
            dst_name.ToCString());
}


void AstPrinter::VisitPrimaryNode(PrimaryNode* node) {
  OS::Print("***** PRIMARY NODE IN AST ***** (%s '%s')",
      node->Name(), node->primary().ToCString());
}


void AstPrinter::VisitComparisonNode(ComparisonNode* node) {
  if (node->kind() == Token::kAS) {
    OS::Print("(as ");
    node->VisitChildren(this);
    OS::Print(")");
  } else {
    VisitGenericAstNode(node);
  }
}


void AstPrinter::VisitBinaryOpNode(BinaryOpNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitUnaryOpNode(UnaryOpNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitConditionalExprNode(ConditionalExprNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitIfNode(IfNode* node) {
  OS::Print("(if ");
  node->condition()->Visit(this);
  OS::Print(" then ");
  node->true_branch()->Visit(this);
  OS::Print(" else ");
  if (node->false_branch() != NULL) {
    node->false_branch()->Visit(this);
  }
  OS::Print(")");
}


void AstPrinter::VisitCaseNode(CaseNode* node) {
  OS::Print("(case (");
  for (int i = 0; i < node->case_expressions()->length(); i++) {
    node->case_expressions()->NodeAt(i)->Visit(this);
  }
  if (node->contains_default()) {
    OS::Print(" default ");
  }
  OS::Print(")");
  node->statements()->Visit(this);
  OS::Print(")");
}


void AstPrinter::VisitSwitchNode(SwitchNode* node) {
  OS::Print("(switch ");
  node->body()->Visit(this);
  OS::Print(")");
}


void AstPrinter::VisitWhileNode(WhileNode* node) {
  OS::Print("(while ");
  node->condition()->Visit(this);
  OS::Print(" do ");
  node->body()->Visit(this);
  OS::Print(")");
}


void AstPrinter::VisitForNode(ForNode* node) {
  OS::Print("(for (init: ");
  node->initializer()->Visit(this);
  OS::Print("; cond:");
  if (node->condition() != NULL) {
    node->condition()->Visit(this);
  }
  OS::Print("; incr:");
  node->increment()->Visit(this);
  OS::Print(") body:");
  node->body()->Visit(this);
  OS::Print("endfor)");
}


void AstPrinter::VisitDoWhileNode(DoWhileNode* node) {
  OS::Print("(do ");
  node->body()->Visit(this);
  OS::Print(" while ");
  node->condition()->Visit(this);
  OS::Print(")");
}


void AstPrinter::VisitJumpNode(JumpNode* node) {
  OS::Print("(%s %s in scope %p)",
            node->Name(),
            node->label()->name().ToCString(),
            node->label()->owner());
}


void AstPrinter::VisitInstanceCallNode(InstanceCallNode* node) {
  OS::Print("(%s '%s'(", node->Name(), node->function_name().ToCString());
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitStaticCallNode(StaticCallNode* node) {
  const char* function_fullname = node->function().ToFullyQualifiedCString();
  OS::Print("(%s '%s'(", node->Name(), function_fullname);
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitClosureNode(ClosureNode* node) {
  const char* function_fullname = node->function().ToFullyQualifiedCString();
  OS::Print("(%s '%s')", node->Name(), function_fullname);
}


void AstPrinter::VisitClosureCallNode(ClosureCallNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitConstructorCallNode(ConstructorCallNode* node) {
  const char* kind = node->constructor().IsFactory() ? "factory " : "";
  const char* constructor_name = node->constructor().ToFullyQualifiedCString();
  OS::Print("(%s %s'%s' ((this)", node->Name(), kind, constructor_name);
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitInstanceGetterNode(InstanceGetterNode* node) {
  OS::Print("(%s 'get %s'(", node->Name(), node->field_name().ToCString());
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitInstanceSetterNode(InstanceSetterNode* node) {
  OS::Print("(%s 'set %s'(", node->Name(), node->field_name().ToCString());
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitStaticGetterNode(StaticGetterNode* node) {
  String& class_name = String::Handle(node->cls().Name());
  OS::Print("(%s '%s.%s'(",
            node->Name(),
            class_name.ToCString(),
            node->field_name().ToCString());
  OS::Print("))");
}


void AstPrinter::VisitStaticSetterNode(StaticSetterNode* node) {
  String& class_name = String::Handle(node->cls().Name());
  OS::Print("(%s '%s.%s'(",
      node->Name(), class_name.ToCString(), node->field_name().ToCString());
  node->VisitChildren(this);
  OS::Print("))");
}


void AstPrinter::VisitLoadIndexedNode(LoadIndexedNode* node) {
  OS::Print("(%s%s ", node->Name(), node->IsSuperLoad() ? " super" : "");
  node->VisitChildren(this);
  OS::Print(")");
}


void AstPrinter::VisitStoreIndexedNode(StoreIndexedNode* node) {
  OS::Print("(%s%s ", node->Name(), node->IsSuperStore() ? " super" : "");
  node->VisitChildren(this);
  OS::Print(")");
}


void AstPrinter::VisitNativeBodyNode(NativeBodyNode* node) {
  OS::Print("(native_c call '%s'(%d args))",
            node->native_c_function_name().ToCString(),
            NativeArguments::ParameterCountForResolution(node->function()));
}


void AstPrinter::VisitCatchClauseNode(CatchClauseNode* node) {
  node->VisitChildren(this);
}


void AstPrinter::VisitTryCatchNode(TryCatchNode* node) {
  OS::Print("(");

  // First visit the try block.
  OS::Print("(try block (");
  node->try_block()->Visit(this);
  OS::Print("))");

  // Now visit the catch block if it exists.
  if (node->catch_block() != NULL) {
    OS::Print("(catch block () (");
    node->catch_block()->Visit(this);
    OS::Print("))");
  }

  // Now visit the finally block if it exists.
  if (node->finally_block() != NULL) {
    OS::Print("(finally block () (");
    node->finally_block()->Visit(this);
    OS::Print("))");
  }

  OS::Print(")");
}


void AstPrinter::VisitThrowNode(ThrowNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::VisitInlinedFinallyNode(InlinedFinallyNode* node) {
  VisitGenericAstNode(node);
}


void AstPrinter::PrintNode(AstNode* node) {
  ASSERT(node != NULL);
  AstPrinter ast_printer;
  node->Visit(&ast_printer);
  OS::Print("\n");
}


void AstPrinter::PrintLocalScope(const LocalScope* scope,
                                 int start_index) {
  ASSERT(scope != NULL);
  for (int i = start_index; i < scope->num_variables(); i++) {
    LocalVariable* var = scope->VariableAt(i);
    OS::Print("(%s%s '%s'",
              var->is_final() ? "final " : "",
              String::Handle(var->type().Name()).ToCString(),
              var->name().ToCString());
    if (var->owner() != scope) {
      OS::Print(" alias");
    }
    if (var->HasIndex()) {
      OS::Print(" @%d", var->index());
      if (var->is_captured()) {
        OS::Print(" ctx %d", var->owner()->context_level());
      }
    } else if (var->owner()->function_level() != 0) {
      OS::Print(" lev %d", var->owner()->function_level());
    }
    OS::Print(" valid %"Pd"-%"Pd")",
              var->token_pos(),
              scope->end_token_pos());
  }
  const LocalScope* child = scope->child();
  while (child != NULL) {
    OS::Print("{scope %p ", child);
    if (child->HasContextLevel()) {
      OS::Print("ctx %d numctxvar %d ",
                child->context_level(),
                child->num_context_variables());
    }
    OS::Print("llev %d ", child->loop_level());
    PrintLocalScope(child, 0);
    OS::Print("}");
    child = child->sibling();
  }
}


void AstPrinter::PrintFunctionScope(const ParsedFunction& parsed_function) {
  HANDLESCOPE(Isolate::Current());
  const Function& function = parsed_function.function();
  const Array& default_parameter_values =
      parsed_function.default_parameter_values();
  SequenceNode* node_sequence = parsed_function.node_sequence();
  ASSERT(node_sequence != NULL);
  const LocalScope* scope = node_sequence->scope();
  ASSERT(scope != NULL);
  const char* function_name = function.ToFullyQualifiedCString();
  OS::Print("Scope for function '%s' {scope %p ", function_name, scope);
  if (scope->HasContextLevel()) {
    OS::Print("ctx %d numctxvar %d ",
              scope->context_level(),
              scope->num_context_variables());
  }
  OS::Print("llev %d ", scope->loop_level());
  const int num_fixed_params = function.num_fixed_parameters();
  const int num_params = num_fixed_params + function.NumOptionalParameters();
  // Parameters must be listed first and must all appear in the top scope.
  ASSERT(num_params <= scope->num_variables());
  int pos = 0;  // Current position of variable in scope.
  while (pos < num_params) {
    LocalVariable* param = scope->VariableAt(pos);
    ASSERT(param->owner() == scope);
    OS::Print("(param %s%s '%s'",
              param->is_final() ? "final " : "",
              String::Handle(param->type().Name()).ToCString(),
              param->name().ToCString());
    // Print the default value if the parameter is optional.
    if (pos >= num_fixed_params && pos < num_params) {
      const Object& default_parameter_value = Object::Handle(
          default_parameter_values.At(pos - num_fixed_params));
      OS::Print(" =%s", default_parameter_value.ToCString());
    }
    if (param->HasIndex()) {
      OS::Print(" @%d", param->index());
      if (param->is_captured()) {
        OS::Print(" ctx %d", param->owner()->context_level());
      }
    }
    OS::Print(" valid %"Pd"-%"Pd")",
              param->token_pos(),
              scope->end_token_pos());
    pos++;
  }
  // Visit remaining non-parameter variables and children scopes.
  PrintLocalScope(scope, pos);
  OS::Print("}\n");
}


void AstPrinter::PrintFunctionNodes(const ParsedFunction& parsed_function) {
  HANDLESCOPE(Isolate::Current());
  SequenceNode* node_sequence = parsed_function.node_sequence();
  ASSERT(node_sequence != NULL);
  AstPrinter ast_printer;
  const char* function_name =
      parsed_function.function().ToFullyQualifiedCString();
  OS::Print("Ast for function '%s' {\n", function_name);
  node_sequence->Visit(&ast_printer);
  OS::Print("}\n");
}

}  // namespace dart
