// 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/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/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
#include "verilog/CST/verilog_nonterminals.h"

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
