Skip to content

Commit

Permalink
PR #475: Function Class Call
Browse files Browse the repository at this point in the history
Fixes #438

GitHub PR #475

Copybara import of the project:

  - a3f57a4 Function Class Call by MinaToma <[email protected]>
  - e5ad530 Fix Typos by MinaToma <[email protected]>
  - 83daea4 Merge e5ad530 into b46d5... by Mina Toma <[email protected]>

Closes #475

PiperOrigin-RevId: 333119137
  • Loading branch information
MinaToma authored and hzeller committed Sep 22, 2020
1 parent b46d580 commit 4c8b023
Show file tree
Hide file tree
Showing 11 changed files with 630 additions and 33 deletions.
29 changes: 27 additions & 2 deletions verilog/CST/functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ std::vector<verible::TreeSearchMatch> FindAllFunctionOrTaskCalls(
return verible::SearchSyntaxTree(root, NodekFunctionCall());
}

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

const verible::SyntaxTreeNode& GetFunctionHeader(const Symbol& function_decl) {
return GetSubtreeAsNode(function_decl, NodeEnum::kFunctionDeclaration, 0,
NodeEnum::kFunctionHeader);
Expand Down Expand Up @@ -89,17 +94,31 @@ const verible::SyntaxTreeLeaf* GetFunctionName(
return ABSL_DIE_IF_NULL(GetIdentifier(*function_id));
}

const verible::SyntaxTreeNode& GetLocalRootFromFunctionCall(
const verible::Symbol& function_call) {
return GetSubtreeAsNode(function_call, NodeEnum::kFunctionCall, 0,
NodeEnum::kLocalRoot);
}

const verible::SyntaxTreeLeaf* GetFunctionCallName(
const verible::Symbol& function_call) {
const auto& local_root = GetSubtreeAsNode(
function_call, NodeEnum::kFunctionCall, 0, NodeEnum::kLocalRoot);
const auto& local_root = GetLocalRootFromFunctionCall(function_call);

const auto& unqualified_id = GetSubtreeAsNode(
local_root, NodeEnum::kLocalRoot, 0, NodeEnum::kUnqualifiedId);

return ABSL_DIE_IF_NULL(GetIdentifier(unqualified_id));
}

const verible::SyntaxTreeLeaf& GetFunctionCallNameFromCallExtension(
const verible::Symbol& function_call) {
const auto& unqualified_id =
GetSubtreeAsNode(function_call, NodeEnum::kMethodCallExtension, 1,
NodeEnum::kUnqualifiedId);

return *ABSL_DIE_IF_NULL(GetIdentifier(unqualified_id));
}

const verible::SyntaxTreeNode& GetFunctionBlockStatementList(
const verible::Symbol& function_decl) {
return verible::GetSubtreeAsNode(function_decl,
Expand All @@ -113,4 +132,10 @@ const verible::SyntaxTreeNode& GetParenGroupFromCall(
NodeEnum::kParenGroup);
}

const verible::SyntaxTreeNode& GetParenGroupFromCallExtension(
const verible::Symbol& function_call) {
return verible::GetSubtreeAsNode(
function_call, NodeEnum::kMethodCallExtension, 2, NodeEnum::kParenGroup);
}

} // namespace verilog
18 changes: 18 additions & 0 deletions verilog/CST/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ std::vector<verible::TreeSearchMatch> FindAllFunctionDeclarations(
std::vector<verible::TreeSearchMatch> FindAllFunctionOrTaskCalls(
const verible::Symbol&);

// Find all function (or Task) calls extension e.g class_name.function_call().
std::vector<verible::TreeSearchMatch> FindAllFunctionOrTaskCallsExtension(
const verible::Symbol&);

// Returns the function declaration header (return type, id, ports)
const verible::SyntaxTreeNode& GetFunctionHeader(
const verible::Symbol& function_decl);
Expand Down Expand Up @@ -119,10 +123,19 @@ const verible::Symbol* GetFunctionId(const verible::Symbol& function_decl);
// e.g. function my_fun(); return leaf node for "my_fun".
const verible::SyntaxTreeLeaf* GetFunctionName(const verible::Symbol&);

// Returns local root node from node tagged with kFunctionCall.
const verible::SyntaxTreeNode& GetLocalRootFromFunctionCall(
const verible::Symbol&);

// Returns leaf node for function name in function call.
// e.g my_function(); return leaf node for "my_function".
const verible::SyntaxTreeLeaf* GetFunctionCallName(const verible::Symbol&);

// Returns leaf node for function name in function call extension.
// e.g class_name.my_function(); return leaf node for "my_function".
const verible::SyntaxTreeLeaf& GetFunctionCallNameFromCallExtension(
const verible::Symbol&);

// Returns the function declaration body.
const verible::SyntaxTreeNode& GetFunctionBlockStatementList(
const verible::Symbol&);
Expand All @@ -131,6 +144,11 @@ const verible::SyntaxTreeNode& GetFunctionBlockStatementList(
// e.g my_function(a, b, c) return the node spanning (a, b, c).
const verible::SyntaxTreeNode& GetParenGroupFromCall(const verible::Symbol&);

// Return the node spanning the paren group of function call extension.
// e.g my_class.my_function(a, b, c) return the node spanning (a, b, c).
const verible::SyntaxTreeNode& GetParenGroupFromCallExtension(
const verible::Symbol&);

} // namespace verilog

#endif // VERIBLE_VERILOG_CST_FUNCTIONS_H_
64 changes: 64 additions & 0 deletions verilog/CST/functions_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,37 @@ TEST(GetFunctionHeaderTest, GetFunctionName) {
}
}

TEST(GetFunctionHeaderTest, GetFunctionClassCallName) {
constexpr int kTag = 1; // value doesn't matter
const SyntaxTreeSearchTestCase kTestCases[] = {
{""},
{"module m(); endmodule: m"},
{"module m();\n initial $display(my_class.",
{kTag, "function_name"},
"());\nendmodule"},
{"module m();\n initial "
"$display(pkg::my_class.",
{kTag, "function_name"},
"());\nendmodule"},
};
for (const auto& test : kTestCases) {
TestVerilogSyntaxRangeMatches(
__FUNCTION__, test, [](const TextStructureView& text_structure) {
const auto& root = text_structure.SyntaxTree();
const auto calls =
FindAllFunctionOrTaskCallsExtension(*ABSL_DIE_IF_NULL(root));

std::vector<TreeSearchMatch> names;
for (const auto& Call : calls) {
const auto& name =
GetFunctionCallNameFromCallExtension(*Call.match);
names.emplace_back(TreeSearchMatch{&name, {/* ignored context */}});
}
return names;
});
}
}

TEST(GetFunctionBlockStatement, GetFunctionBody) {
constexpr int kTag = 1; // value doesn't matter
const SyntaxTreeSearchTestCase kTestCases[] = {
Expand Down Expand Up @@ -536,5 +567,38 @@ TEST(FunctionCallTest, GetFunctionCallArguments) {
}
}

TEST(FunctionCallTest, GetFunctionCallExtensionArguments) {
constexpr int kTag = 1; // value doesn't matter
const SyntaxTreeSearchTestCase kTestCases[] = {
{""},
{"module m(); endmodule: m"},
{"module m();\n initial $display(my_class.function_name",
{kTag, "(x, y)"},
");\nendmodule"},
{"module m();\n initial "
"$display(pkg::my_class.function_name",
{kTag, "()"},
");\nendmodule"},
};

for (const auto& test : kTestCases) {
TestVerilogSyntaxRangeMatches(
__FUNCTION__, test, [](const TextStructureView& text_structure) {
const auto& root = text_structure.SyntaxTree();
const auto& instances =
FindAllFunctionOrTaskCallsExtension(*ABSL_DIE_IF_NULL(root));

std::vector<TreeSearchMatch> paren_groups;
for (const auto& decl : instances) {
const auto& paren_group =
GetParenGroupFromCallExtension(*decl.match);
paren_groups.emplace_back(
TreeSearchMatch{&paren_group, {/* ignored context */}});
}
return paren_groups;
});
}
}

} // namespace
} // namespace verilog
54 changes: 49 additions & 5 deletions verilog/tools/kythe/indexing_facts_tree_extractor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ void IndexingFactsTreeExtractor::Visit(const SyntaxTreeNode& node) {
ExtractFunctionOrTaskCall(node);
break;
}
case NodeEnum::kMethodCallExtension: {
ExtractMethodCallExtension(node);
break;
}
case NodeEnum::kClassDeclaration: {
ExtractClassDeclaration(node);
break;
Expand Down Expand Up @@ -563,23 +567,63 @@ void IndexingFactsTreeExtractor::ExtractFunctionOrTaskCall(
IndexingFactNode function_node(function_node_data);

// Extract function or task name.
const auto* function_name_leaf = GetFunctionCallName(function_call_node);
const Anchor task_name_anchor(function_name_leaf->get(), context_.base);
function_node.Value().AppendAnchor(task_name_anchor);
// It can be single or preceeded with a pkg or class names.
const SyntaxTreeNode& local_root =
GetLocalRootFromFunctionCall(function_call_node);
const std::vector<TreeSearchMatch> unqualified_ids =
FindAllUnqualifiedIds(local_root);
for (const TreeSearchMatch& unqualified_id : unqualified_ids) {
function_node.Value().AppendAnchor(Anchor(
AutoUnwrapIdentifier(*unqualified_id.match)->get(), context_.base));
}

{
const IndexingFactsTreeContext::AutoPop p(&facts_tree_context_,
&function_node);

const SyntaxTreeNode& arguments = GetParenGroupFromCall(function_call_node);

// Extract function or task parameters.
Visit(arguments);
}

facts_tree_context_.top().NewChild(function_node);
}

void IndexingFactsTreeExtractor::ExtractMethodCallExtension(
const verible::SyntaxTreeNode& call_extension_node) {
IndexingNodeData function_node_data(IndexingFactType::kFunctionCall);
IndexingFactNode function_node(function_node_data);

const IndexingFactNode& previous_node =
facts_tree_context_.top().Children().back();

// Fill the anchors of the previous node to the current node.
// Previous node should be a kMemberReference or kVariableReference.
for (const Anchor& anchor : previous_node.Value().Anchors()) {
function_node.Value().AppendAnchor(anchor);
}

// Remove the last node as it was either kMemberReference or
// kVariableReference.
// The node is removed so that it can be treated as a function call.
facts_tree_context_.top().Children().pop_back();

const SyntaxTreeLeaf& function_name =
GetFunctionCallNameFromCallExtension(call_extension_node);
function_node.Value().AppendAnchor(
Anchor(function_name.get(), context_.base));

{
const IndexingFactsTreeContext::AutoPop p(&facts_tree_context_,
&function_node);
const SyntaxTreeNode& arguments =
GetParenGroupFromCallExtension(call_extension_node);
// parameters.
Visit(arguments);
}

facts_tree_context_.top().NewChild(function_node);
}

void IndexingFactsTreeExtractor::ExtractClassDeclaration(
const SyntaxTreeNode& class_declaration) {
IndexingNodeData class_node_data(IndexingFactType::kClass);
Expand Down
5 changes: 5 additions & 0 deletions verilog/tools/kythe/indexing_facts_tree_extractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class IndexingFactsTreeExtractor : public verible::TreeContextVisitor {
void ExtractFunctionOrTaskCall(
const verible::SyntaxTreeNode& function_call_node);

// Extracts function or task call tagged with kMethodCallExtension (treated as
// kFunctionOrTaskCall in facts tree) creates its corresponding fact tree.
void ExtractMethodCallExtension(
const verible::SyntaxTreeNode& call_extension_node);

// Extracts function or task ports and parameters.
void ExtractFunctionTaskPort(
const verible::SyntaxTreeNode& function_declaration_node);
Expand Down
Loading

0 comments on commit 4c8b023

Please sign in to comment.