// Copyright 2017-2023 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->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->size() < 2) return nullptr;
  const Symbol *else_ptr = node->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->size() < 2) return nullptr;
  const Symbol *else_ptr = node->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->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->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->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->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->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);
  const verible::SyntaxTreeNode *local_root =
      GetLocalRootFromReference(*lpvalue);
  if (!local_root) return nullptr;
  const verible::Symbol *identifiers = GetIdentifiersFromLocalRoot(*local_root);
  return AutoUnwrapIdentifier(*identifiers);
}

// 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);
}

const verible::SyntaxTreeNode *GetProceduralTimingControlFromAlways(
    const verible::SyntaxTreeNode &always_statement) {
  return verible::GetSubtreeAsNode(always_statement, NodeEnum::kAlwaysStatement,
                                   1,
                                   NodeEnum::kProceduralTimingControlStatement);
}

const verible::Symbol *GetEventControlFromProceduralTimingControl(
    const verible::SyntaxTreeNode &proc_timing_ctrl) {
  return verible::GetSubtreeAsNode(proc_timing_ctrl,
                                   NodeEnum::kProceduralTimingControlStatement,
                                   0, NodeEnum::kEventControl);
}

}  // namespace verilog
