// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// ConcreteSyntaxTree represents the structure of a body of text.
//
// This header also provides the following (owernship-transferring) functions
// for constructing syntax trees in semantic action blocks:
//
//   $$ = MakeNode($1, $2, ...);
//   $$ = MakeTaggedNode(kTag, $1, $2, ...);
//   $$ = ExtendNode($1, $2, ...);
//   $$ = MakeNode($1, ForwardChildren($2), $3, ...);
//
// As ownership is transferred exclusively, the pointers left behind are
// null as a result.
//
// These functions are intended for use only in <language>.yc semantic actions.
//
// The std::move is automated for the sake of easy tree building.
// Without the automation, the user would have to write:
//   $$ = MakeNode(std::move($1), std::move($2), ...);
// which would be less readable than the above.

#ifndef VERIBLE_COMMON_TEXT_CONCRETE_SYNTAX_TREE_H_
#define VERIBLE_COMMON_TEXT_CONCRETE_SYNTAX_TREE_H_

#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <memory>
#include <utility>
#include <vector>

#include "common/text/constants.h"
#include "common/text/symbol.h"
#include "common/text/tree_compare.h"
#include "common/text/visitors.h"
#include "common/util/casts.h"
#include "common/util/logging.h"

namespace verible {

// Using unique_ptr in the symbol stack requires careful moving.
using SymbolPtr = std::unique_ptr<Symbol>;

// Currently, a tree *is* a tree-node, but this may change in the future.
// Treat this as an opaque type.
using ConcreteSyntaxTree = SymbolPtr;

// Helper class for transferring ownership of children, which is
// used as an overload to SyntaxTreeNode::AppendChild.
// This takes over ownership of the symbol pointer.
//    $$ = MakeNode($1, $2, ForwardChildren($3), $4);
struct ForwardChildren {
  explicit ForwardChildren(SymbolPtr& symbol)  // NOLINT
      : node(std::move(symbol)) {}
  SymbolPtr node;
};

// SyntaxTreeNode is a language-agnostic node structure, supporting an
// arbitrary number of children.  The 'tag' field is a node type enumeration
// used by various language front-ends.
class SyntaxTreeNode final : public Symbol {
 public:
  explicit SyntaxTreeNode(const int tag = kUntagged) : tag_(tag) {}

  const std::vector<SymbolPtr>& children() const { return children_; }
  std::vector<SymbolPtr>& mutable_children() { return children_; }

  // Transfer ownership of argument to this object.
  // Call MakeNode or ExtendNode instead of calling this directly.
  void AppendChild(SymbolPtr child) { children_.push_back(std::move(child)); }

  // Transfer ownership of argument's children to this object.
  // Call MakeNode or ExtendNode instead of calling this directly.
  // If node is actually a leaf, just append the leaf.
  void AppendChild(ForwardChildren forwarded_children) {
    if (forwarded_children.node == nullptr) return;
    auto* node = dynamic_cast<SyntaxTreeNode*>(forwarded_children.node.get());
    if (node == nullptr) {
      // Could be a SyntaxTreeLeaf, for instance.
      children_.push_back(std::move(forwarded_children.node));
      return;
    }
    const auto new_size = children_.size() + node->children_.size();
    children_.reserve(new_size);
    for (auto& child : node->children_) {
      children_.push_back(std::move(child));
    }
    // Remove all the vacated children slots left in the parent.
    node->children_.clear();
  }

  // This no-op case is the base case for the variadic Append.
  void Append() const {}

  // Ownership of all arguments is transferred to this object.
  // Call MakeNode or ExtendNode instead of calling Append directly.
  template <typename T, typename... Args>
  void Append(T&& t, Args&&... args) {
    AppendChild(std::move(t));            // Append the first.
    Append(std::forward<Args>(args)...);  // Append the rest.
  }

  // Children accessor (mutable).
  SymbolPtr& operator[](size_t i);

  // Children accessor (const).
  const SymbolPtr& operator[](size_t i) const;

  // Compares this node to an arbitrary symbol using the compare_tokens
  // function.
  bool equals(const Symbol* symbol,
              const TokenComparator& compare_tokens) const final;

  // Compares this node to another node.
  // Checks for recursive equality among all children of both nodes.
  bool equals(const SyntaxTreeNode* node,
              const TokenComparator& compare_tokens) const;

  // Uses passed TreeVisitorRecursive to visit all children recursively,
  // then visit itself.
  void Accept(TreeVisitorRecursive* visitor) const final;
  void Accept(MutableTreeVisitorRecursive* visitor,
              SymbolPtr* this_owned) final;

  // Accepting a symbol visitor does not recursively visit children.
  void Accept(SymbolVisitor* visitor) const final;

  // Method override that returns the Kind of Symbol
  SymbolKind Kind() const final { return SymbolKind::kNode; }
  SymbolTag Tag() const final { return NodeTag(tag_); }

  // MatchesTag returns true if the tag value matches the argument.
  // This is designed to work with any enumeration type.
  template <typename EnumType>
  bool MatchesTag(EnumType e) const {
    return tag_ == static_cast<int>(e);
  }

  template <typename EnumType>
  bool MatchesTagAnyOf(std::initializer_list<EnumType> enums) const {
    auto it = enums.begin();
    // Unroll OR expression. Right now, we never have more than 4.
    switch (enums.size()) {
      case 4:
        if (*it++ == EnumType(tag_)) return true;
        ABSL_FALLTHROUGH_INTENDED;
      case 3:
        if (*it++ == EnumType(tag_)) return true;
        ABSL_FALLTHROUGH_INTENDED;
      case 2:
        if (*it++ == EnumType(tag_)) return true;
        ABSL_FALLTHROUGH_INTENDED;
      case 1:
        if (*it++ == EnumType(tag_)) return true;
        ABSL_FALLTHROUGH_INTENDED;
      case 0:
        return false;
      default:
        // TODO(hzeller): with constexpr magic, can we static_assert() this ?
        LOG(FATAL) << "need more choice " << enums.size();
        return false;
    }
  }

 private:
  // This tag would really prefer to be a language-specific node enumeration
  // type, but that would (IMHO) create unecessary templating.
  // Decision: Keep this a generic int.
  int tag_;

  // Sequence of pointers to subtrees and nodes.
  std::vector<SymbolPtr> children_;
};

// The following functions are intended for use in semantic action blocks
// in yacc/bison grammar files (.yc).

// Construct a syntax tree node with a tag.
// Ownership of all args is transferred, and consumed by the new node.
// Sample usage: $$ = MakeNode(TAG, $1, $2, $3);
template <typename... Args>
SymbolPtr MakeNode(Args&&... args) {
  std::unique_ptr<SyntaxTreeNode> node_pointer(new SyntaxTreeNode);
  node_pointer->Append(std::forward<Args>(args)...);
  return std::move(node_pointer);
}

// Construct a syntax tree node with a tag.
// Ownership of all args is transferred, and consumed by the new node.
// Sample usage:
//   $$ = MakeTaggedNode(TAG);  // empty, no children
//   $$ = MakeTaggedNode(TAG, $1, $2, $3);
template <typename Enum, typename... Args>
SymbolPtr MakeTaggedNode(const Enum tag, Args&&... args) {
  std::unique_ptr<SyntaxTreeNode> node_pointer(
      new SyntaxTreeNode(static_cast<int>(tag)));
  node_pointer->Append(std::forward<Args>(args)...);
  return std::move(node_pointer);
}

// Extend the children of an existing node.
// Equivalent to: $$ = std::move(ExtendNode($1, $2, $3));
// Ownership of all args is transferred, and consumed by the existing node.
// $1 is transferred to $$.
// Sample usage: $$ = ExtendNode($1, $2, $3);
template <typename T, typename... Args>
SymbolPtr ExtendNode(T&& list_ptr, Args&&... args) {
  return _ExtendNodeMoved(std::move(list_ptr), std::forward<Args>(args)...);
}

// Implementation detail, call ExtendNode instead for automatic std::move.
template <typename... Args>
SymbolPtr _ExtendNodeMoved(SymbolPtr list_ptr, Args&&... args) {
  CHECK(list_ptr->Kind() == SymbolKind::kNode);
  SyntaxTreeNode* node_pointer = down_cast<SyntaxTreeNode*>(list_ptr.get());
  node_pointer->Append(std::forward<Args>(args)...);
  return list_ptr;
}

// Helper function to deal with move semantics and argument forwarding
void SetChild_(const SymbolPtr& parent, int child_index, SymbolPtr new_child);

// Sets the child at child_index of parent to new_child.
// SetChild will crash when:
//   Child_index is out of range
//   Parent either a leaf or a nullptr
//   Preexisting data at target index is not a nullptr
// Equivalent to: parent->children[child_index] = std::move(new_child);
template <typename T>
void SetChild(const SymbolPtr& parent, int child_index, T&& new_child) {
  SetChild_(parent, child_index, std::move(new_child));
}

}  // namespace verible

#endif  // VERIBLE_COMMON_TEXT_CONCRETE_SYNTAX_TREE_H_
