blob: cba5f7511f477299bdea56a5aa47045ab4f2e820 [file] [log] [blame]
// 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