// 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.

#include "verilog/CST/statement.h"

#include <vector>

#include "common/analysis/matcher/matcher.h"
#include "common/analysis/matcher/matcher_builders.h"
#include "common/analysis/syntax_tree_search.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"
#include "common/text/token_info.h"
#include "common/text/tree_utils.h"
#include "verilog/CST/declaration.h"
#include "verilog/CST/identifier.h"
#include "verilog/CST/type.h"
#include "verilog/CST/verilog_matchers.h"  // IWYU pragma: keep

namespace verilog {

using verible::Symbol;
using verible::SymbolCastToNode;
using verible::SyntaxTreeNode;

std::vector<verible::TreeSearchMatch> FindAllForLoopsInitializations(
    const verible::Symbol& root) {
  return SearchSyntaxTree(root, NodekForInitialization());
}

std::vector<verible::TreeSearchMatch> FindAllGenerateBlocks(
    const verible::Symbol& root) {
  return SearchSyntaxTree(root, NodekGenerateBlock());
}

static const SyntaxTreeNode* GetGenericStatementBody(
    const SyntaxTreeNode* node) {
  if (!node) return node;
  // In most controlled constructs, the controlled statement body is
  // in tail position.  Exceptions include: DoWhile.
  return &SymbolCastToNode(*node->children().back());
}

const SyntaxTreeNode* GetIfClauseGenerateBody(const Symbol& if_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(if_clause), NodeEnum::kGenerateIfClause));
  if (!body_node) return nullptr;
  return GetSubtreeAsNode(*body_node, NodeEnum::kGenerateIfBody, 0);
}

const SyntaxTreeNode* GetElseClauseGenerateBody(const Symbol& else_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(else_clause), NodeEnum::kGenerateElseClause));
  if (!body_node) return nullptr;
  return GetSubtreeAsNode(*body_node, NodeEnum::kGenerateElseBody, 0);
}

const SyntaxTreeNode* GetLoopGenerateBody(const Symbol& loop) {
  return GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(loop), NodeEnum::kLoopGenerateConstruct));
}

const SyntaxTreeNode* GetConditionalGenerateIfClause(
    const Symbol& conditional) {
  return GetSubtreeAsNode(conditional, NodeEnum::kConditionalGenerateConstruct,
                          0, NodeEnum::kGenerateIfClause);
}

const SyntaxTreeNode* GetConditionalGenerateElseClause(
    const Symbol& conditional) {
  const auto* node = MatchNodeEnumOrNull(
      SymbolCastToNode(conditional), NodeEnum::kConditionalGenerateConstruct);
  if (!node || node->children().size() < 2) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kGenerateElseClause);
}

const SyntaxTreeNode* GetIfClauseStatementBody(const Symbol& if_clause) {
  const auto* body_node = GetGenericStatementBody(
      MatchNodeEnumOrNull(SymbolCastToNode(if_clause), NodeEnum::kIfClause));
  if (!body_node) return nullptr;
  return GetSubtreeAsNode(*body_node, NodeEnum::kIfBody, 0);
}

const SyntaxTreeNode* GetElseClauseStatementBody(const Symbol& else_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(else_clause), NodeEnum::kElseClause));
  if (!body_node) return nullptr;
  return GetSubtreeAsNode(*body_node, NodeEnum::kElseBody, 0);
}

const SyntaxTreeNode* GetConditionalStatementIfClause(
    const Symbol& conditional) {
  return GetSubtreeAsNode(conditional, NodeEnum::kConditionalStatement, 0,
                          NodeEnum::kIfClause);
}

const SyntaxTreeNode* GetConditionalStatementElseClause(
    const Symbol& conditional) {
  const auto* node = MatchNodeEnumOrNull(SymbolCastToNode(conditional),
                                         NodeEnum::kConditionalStatement);
  if (!node || node->children().size() < 2) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetAssertionStatementAssertClause(
    const Symbol& assertion_statement) {
  return GetSubtreeAsNode(assertion_statement, NodeEnum::kAssertionStatement, 0,
                          NodeEnum::kAssertionClause);
}

const SyntaxTreeNode* GetAssertionClauseStatementBody(
    const Symbol& assertion_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(assertion_clause), NodeEnum::kAssertionClause));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kAssertionBody, 0));
}

const SyntaxTreeNode* GetAssertionStatementElseClause(
    const Symbol& assertion_statement) {
  const auto* node = MatchNodeEnumOrNull(SymbolCastToNode(assertion_statement),
                                         NodeEnum::kAssertionStatement);
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetAssumeStatementAssumeClause(
    const Symbol& assume_statement) {
  return GetSubtreeAsNode(assume_statement, NodeEnum::kAssumeStatement, 0,
                          NodeEnum::kAssumeClause);
}

const SyntaxTreeNode* GetAssumeClauseStatementBody(
    const Symbol& assume_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(assume_clause), NodeEnum::kAssumeClause));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kAssumeBody, 0));
}

const SyntaxTreeNode* GetAssumeStatementElseClause(
    const Symbol& assume_statement) {
  const auto* node = MatchNodeEnumOrNull(SymbolCastToNode(assume_statement),
                                         NodeEnum::kAssumeStatement);
  if (!node) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetCoverStatementBody(const Symbol& cover_statement) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(cover_statement), NodeEnum::kCoverStatement));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kCoverBody, 0));
}

const SyntaxTreeNode* GetWaitStatementBody(const Symbol& wait_statement) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(wait_statement), NodeEnum::kWaitStatement));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kWaitBody, 0));
}

const SyntaxTreeNode* GetAssertPropertyStatementAssertClause(
    const Symbol& assert_property_statement) {
  return GetSubtreeAsNode(assert_property_statement,
                          NodeEnum::kAssertPropertyStatement, 0,
                          NodeEnum::kAssertPropertyClause);
}

const SyntaxTreeNode* GetAssertPropertyStatementBody(
    const Symbol& assert_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(assert_clause), NodeEnum::kAssertPropertyClause));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kAssertPropertyBody, 0));
}

const SyntaxTreeNode* GetAssertPropertyStatementElseClause(
    const Symbol& assert_property_statement) {
  const auto* node =
      MatchNodeEnumOrNull(SymbolCastToNode(assert_property_statement),
                          NodeEnum::kAssertPropertyStatement);
  if (!node) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetAssumePropertyStatementAssumeClause(
    const Symbol& assume_property_statement) {
  return GetSubtreeAsNode(assume_property_statement,
                          NodeEnum::kAssumePropertyStatement, 0,
                          NodeEnum::kAssumePropertyClause);
}

const SyntaxTreeNode* GetAssumePropertyStatementBody(
    const Symbol& assume_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(assume_clause), NodeEnum::kAssumePropertyClause));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kAssumePropertyBody, 0));
}

const SyntaxTreeNode* GetAssumePropertyStatementElseClause(
    const Symbol& assume_property_statement) {
  const auto* node =
      MatchNodeEnumOrNull(SymbolCastToNode(assume_property_statement),
                          NodeEnum::kAssumePropertyStatement);
  if (!node) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetExpectPropertyStatementExpectClause(
    const Symbol& expect_property_statement) {
  return GetSubtreeAsNode(expect_property_statement,
                          NodeEnum::kExpectPropertyStatement, 0,
                          NodeEnum::kExpectPropertyClause);
}

const SyntaxTreeNode* GetExpectPropertyStatementBody(
    const Symbol& expect_clause) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(expect_clause), NodeEnum::kExpectPropertyClause));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kExpectPropertyBody, 0));
}

const SyntaxTreeNode* GetExpectPropertyStatementElseClause(
    const Symbol& expect_property_statement) {
  const auto* node =
      MatchNodeEnumOrNull(SymbolCastToNode(expect_property_statement),
                          NodeEnum::kExpectPropertyStatement);
  if (!node) return nullptr;
  const Symbol* else_ptr = node->children().back().get();
  if (else_ptr == nullptr) return nullptr;
  return MatchNodeEnumOrNull(SymbolCastToNode(*else_ptr),
                             NodeEnum::kElseClause);
}

const SyntaxTreeNode* GetCoverPropertyStatementBody(
    const Symbol& cover_property) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(cover_property), NodeEnum::kCoverPropertyStatement));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kCoverPropertyBody, 0));
}

const SyntaxTreeNode* GetCoverSequenceStatementBody(
    const Symbol& cover_sequence) {
  const auto* body_node = GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(cover_sequence), NodeEnum::kCoverSequenceStatement));
  if (!body_node) return nullptr;
  return verible::CheckOptionalSymbolAsNode(
      GetSubtreeAsSymbol(*body_node, NodeEnum::kCoverSequenceBody, 0));
}

const SyntaxTreeNode* GetLoopStatementBody(const Symbol& loop) {
  return GetGenericStatementBody(
      MatchNodeEnumOrNull(SymbolCastToNode(loop), NodeEnum::kForLoopStatement));
}

const SyntaxTreeNode* GetDoWhileStatementBody(const Symbol& do_while) {
  return GetSubtreeAsNode(SymbolCastToNode(do_while),
                          NodeEnum::kDoWhileLoopStatement, 1);
}

const SyntaxTreeNode* GetForeverStatementBody(const Symbol& forever) {
  return GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(forever), NodeEnum::kForeverLoopStatement));
}

const SyntaxTreeNode* GetForeachStatementBody(const Symbol& foreach) {
  return GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(foreach), NodeEnum::kForeachLoopStatement));
}

const SyntaxTreeNode* GetRepeatStatementBody(const Symbol& repeat) {
  return GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(repeat), NodeEnum::kRepeatLoopStatement));
}

const SyntaxTreeNode* GetWhileStatementBody(const Symbol& while_stmt) {
  return GetGenericStatementBody(MatchNodeEnumOrNull(
      SymbolCastToNode(while_stmt), NodeEnum::kWhileLoopStatement));
}

const SyntaxTreeNode* GetProceduralTimingControlStatementBody(
    const Symbol& proc_timing_control) {
  return GetGenericStatementBody(
      MatchNodeEnumOrNull(SymbolCastToNode(proc_timing_control),
                          NodeEnum::kProceduralTimingControlStatement));
}

const SyntaxTreeNode* GetAnyControlStatementBody(const Symbol& statement) {
  switch (NodeEnum(SymbolCastToNode(statement).Tag().tag)) {
    // generate
    case NodeEnum::kGenerateIfClause:
      return GetIfClauseGenerateBody(statement);
    case NodeEnum::kGenerateElseClause:
      return GetElseClauseGenerateBody(statement);
    case NodeEnum::kLoopGenerateConstruct:
      return GetLoopGenerateBody(statement);

    // statements
    case NodeEnum::kIfClause:
      return GetIfClauseStatementBody(statement);
    case NodeEnum::kElseClause:
      return GetElseClauseStatementBody(statement);
    case NodeEnum::kForLoopStatement:
      return GetLoopStatementBody(statement);
    case NodeEnum::kDoWhileLoopStatement:
      return GetDoWhileStatementBody(statement);
    case NodeEnum::kForeverLoopStatement:
      return GetForeverStatementBody(statement);
    case NodeEnum::kForeachLoopStatement:
      return GetForeachStatementBody(statement);
    case NodeEnum::kRepeatLoopStatement:
      return GetRepeatStatementBody(statement);
    case NodeEnum::kWhileLoopStatement:
      return GetWhileStatementBody(statement);
    case NodeEnum::kProceduralTimingControlStatement:
      return GetProceduralTimingControlStatementBody(statement);

    // immediate assertions
    case NodeEnum::kAssertionClause:
      return GetAssertionClauseStatementBody(statement);
    case NodeEnum::kAssumeClause:
      return GetAssumeClauseStatementBody(statement);
    case NodeEnum::kCoverStatement:
      return GetCoverStatementBody(statement);

    case NodeEnum::kWaitStatement:
      return GetWaitStatementBody(statement);

    // concurrent assertions
    case NodeEnum::kAssertPropertyClause:
      return GetAssertPropertyStatementBody(statement);
    case NodeEnum::kAssumePropertyClause:
      return GetAssumePropertyStatementBody(statement);
    case NodeEnum::kExpectPropertyClause:
      return GetExpectPropertyStatementBody(statement);
    case NodeEnum::kCoverPropertyStatement:
      return GetCoverPropertyStatementBody(statement);
    case NodeEnum::kCoverSequenceStatement:
      return GetCoverSequenceStatementBody(statement);

    default:
      return nullptr;
  }
}

const SyntaxTreeNode* GetAnyConditionalIfClause(const Symbol& conditional) {
  // by IfClause, we main the first clause
  switch (NodeEnum(SymbolCastToNode(conditional).Tag().tag)) {
    // generate
    case NodeEnum::kConditionalGenerateConstruct:
      return GetConditionalGenerateIfClause(conditional);

    // statement
    case NodeEnum::kConditionalStatement:
      return GetConditionalStatementIfClause(conditional);

      // immediate assertions
    case NodeEnum::kAssertionStatement:
      return GetAssertionStatementAssertClause(conditional);
    case NodeEnum::kAssumeStatement:
      return GetAssumeStatementAssumeClause(conditional);

      // concurrent assertions
    case NodeEnum::kAssertPropertyStatement:
      return GetAssertPropertyStatementAssertClause(conditional);
    case NodeEnum::kAssumePropertyStatement:
      return GetAssumePropertyStatementAssumeClause(conditional);
    case NodeEnum::kExpectPropertyStatement:
      return GetExpectPropertyStatementExpectClause(conditional);

    default:
      return nullptr;
  }
}

const SyntaxTreeNode* GetAnyConditionalElseClause(const Symbol& conditional) {
  switch (NodeEnum(SymbolCastToNode(conditional).Tag().tag)) {
    // generate
    case NodeEnum::kConditionalGenerateConstruct:
      return GetConditionalGenerateElseClause(conditional);

    // statement
    case NodeEnum::kConditionalStatement:
      return GetConditionalStatementElseClause(conditional);

      // immediate assertions
    case NodeEnum::kAssertionStatement:
      return GetAssertionStatementElseClause(conditional);
    case NodeEnum::kAssumeStatement:
      return GetAssumeStatementElseClause(conditional);

      // concurrent assertions
    case NodeEnum::kAssertPropertyStatement:
      return GetAssertPropertyStatementElseClause(conditional);
    case NodeEnum::kAssumePropertyStatement:
      return GetAssumePropertyStatementElseClause(conditional);
    case NodeEnum::kExpectPropertyStatement:
      return GetExpectPropertyStatementElseClause(conditional);

    default:
      return nullptr;
  }
}

// Returns the data type node from for loop initialization.
const verible::SyntaxTreeNode* GetDataTypeFromForInitialization(
    const verible::Symbol& for_initialization) {
  const auto* data_type = verible::GetSubtreeAsSymbol(
      for_initialization, NodeEnum::kForInitialization, 1);
  if (data_type == nullptr) {
    return nullptr;
  }
  return &verible::SymbolCastToNode(*data_type);
}

// Returns the variable name leaf from for loop initialization.
const verible::SyntaxTreeLeaf* GetVariableNameFromForInitialization(
    const verible::Symbol& for_initialization) {
  const Symbol* child = verible::GetSubtreeAsSymbol(
      for_initialization, NodeEnum::kForInitialization, 2);
  if (child->Kind() == verible::SymbolKind::kLeaf) {
    return &SymbolCastToLeaf(*child);
  }
  const verible::SyntaxTreeNode* lpvalue =
      verible::GetSubtreeAsNode(*child, NodeEnum::kLPValue, 0);
  return AutoUnwrapIdentifier(*GetUnqualifiedIdFromReferenceCallBase(*lpvalue));
}

// Returns the rhs expression from for loop initialization.
const verible::SyntaxTreeNode* GetExpressionFromForInitialization(
    const verible::Symbol& for_initialization) {
  return verible::GetSubtreeAsNode(for_initialization,
                                   NodeEnum::kForInitialization, 4,
                                   NodeEnum::kExpression);
}

const verible::SyntaxTreeNode* GetGenerateBlockBegin(
    const verible::Symbol& generate_block) {
  return verible::GetSubtreeAsNode(generate_block, NodeEnum::kGenerateBlock, 0,
                                   NodeEnum::kBegin);
}

const verible::SyntaxTreeNode* GetGenerateBlockEnd(
    const verible::Symbol& generate_block) {
  return verible::GetSubtreeAsNode(generate_block, NodeEnum::kGenerateBlock, 2,
                                   NodeEnum::kEnd);
}

}  // namespace verilog
