aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/program-tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/program-tree.cpp')
-rw-r--r--flang/lib/Semantics/program-tree.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp
new file mode 100644
index 0000000..9325079
--- /dev/null
+++ b/flang/lib/Semantics/program-tree.cpp
@@ -0,0 +1,192 @@
+//===-- lib/Semantics/program-tree.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "program-tree.h"
+#include "flang/Common/idioms.h"
+#include "flang/Parser/char-block.h"
+#include "flang/Semantics/scope.h"
+
+namespace Fortran::semantics {
+
+template<typename T>
+static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
+ const auto &spec{std::get<parser::SpecificationPart>(x.t)};
+ const auto &exec{std::get<parser::ExecutionPart>(x.t)};
+ const auto &subps{
+ std::get<std::optional<parser::InternalSubprogramPart>>(x.t)};
+ ProgramTree node{name, spec, &exec};
+ if (subps) {
+ for (const auto &subp :
+ std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
+ std::visit(
+ [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
+ subp.u);
+ }
+ }
+ return node;
+}
+
+static ProgramTree BuildSubprogramTree(
+ const parser::Name &name, const parser::BlockData &x) {
+ const auto &spec{std::get<parser::SpecificationPart>(x.t)};
+ return ProgramTree{name, spec, nullptr};
+}
+
+template<typename T>
+static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
+ const auto &spec{std::get<parser::SpecificationPart>(x.t)};
+ const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)};
+ ProgramTree node{name, spec};
+ if (subps) {
+ for (const auto &subp :
+ std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
+ std::visit(
+ [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
+ subp.u);
+ }
+ }
+ return node;
+}
+
+ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) {
+ return std::visit([](const auto &y) { return Build(y.value()); }, x.u);
+}
+
+ProgramTree ProgramTree::Build(const parser::MainProgram &x) {
+ const auto &stmt{
+ std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)};
+ static parser::Name emptyName;
+ auto result{stmt ? BuildSubprogramTree(stmt->statement.v, x).set_stmt(*stmt)
+ : BuildSubprogramTree(emptyName, x)};
+ return result.set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) {
+ const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)};
+ const auto &name{std::get<parser::Name>(stmt.statement.t)};
+ return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) {
+ const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)};
+ const auto &name{std::get<parser::Name>(stmt.statement.t)};
+ return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::SeparateModuleSubprogram &x) {
+ const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)};
+ const auto &end{
+ std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)};
+ const auto &name{stmt.statement.v};
+ return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::Module &x) {
+ const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)};
+ const auto &name{stmt.statement.v};
+ return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::Submodule &x) {
+ const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)};
+ const auto &name{std::get<parser::Name>(stmt.statement.t)};
+ return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end);
+}
+
+ProgramTree ProgramTree::Build(const parser::BlockData &x) {
+ const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)};
+ const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)};
+ static parser::Name emptyName;
+ auto result{stmt.statement.v ? BuildSubprogramTree(*stmt.statement.v, x)
+ : BuildSubprogramTree(emptyName, x)};
+ return result.set_stmt(stmt).set_endStmt(end);
+}
+
+const parser::ParentIdentifier &ProgramTree::GetParentId() const {
+ const auto *stmt{
+ std::get<const parser::Statement<parser::SubmoduleStmt> *>(stmt_)};
+ return std::get<parser::ParentIdentifier>(stmt->statement.t);
+}
+
+bool ProgramTree::IsModule() const {
+ auto kind{GetKind()};
+ return kind == Kind::Module || kind == Kind::Submodule;
+}
+
+Symbol::Flag ProgramTree::GetSubpFlag() const {
+ return GetKind() == Kind::Function ? Symbol::Flag::Function
+ : Symbol::Flag::Subroutine;
+}
+
+bool ProgramTree::HasModulePrefix() const {
+ using ListType = std::list<parser::PrefixSpec>;
+ const auto *prefixes{std::visit(
+ common::visitors{
+ [](const parser::Statement<parser::FunctionStmt> *x) {
+ return &std::get<ListType>(x->statement.t);
+ },
+ [](const parser::Statement<parser::SubroutineStmt> *x) {
+ return &std::get<ListType>(x->statement.t);
+ },
+ [](const auto *) -> const ListType * { return nullptr; },
+ },
+ stmt_)};
+ if (prefixes) {
+ for (const auto &prefix : *prefixes) {
+ if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+ProgramTree::Kind ProgramTree::GetKind() const {
+ return std::visit(
+ common::visitors{
+ [](const parser::Statement<parser::ProgramStmt> *) {
+ return Kind::Program;
+ },
+ [](const parser::Statement<parser::FunctionStmt> *) {
+ return Kind::Function;
+ },
+ [](const parser::Statement<parser::SubroutineStmt> *) {
+ return Kind::Subroutine;
+ },
+ [](const parser::Statement<parser::MpSubprogramStmt> *) {
+ return Kind::MpSubprogram;
+ },
+ [](const parser::Statement<parser::ModuleStmt> *) {
+ return Kind::Module;
+ },
+ [](const parser::Statement<parser::SubmoduleStmt> *) {
+ return Kind::Submodule;
+ },
+ [](const parser::Statement<parser::BlockDataStmt> *) {
+ return Kind::BlockData;
+ },
+ },
+ stmt_);
+}
+
+void ProgramTree::set_scope(Scope &scope) {
+ scope_ = &scope;
+ CHECK(endStmt_);
+ scope.AddSourceRange(*endStmt_);
+}
+
+void ProgramTree::AddChild(ProgramTree &&child) {
+ children_.emplace_back(std::move(child));
+}
+
+}