1 //===-- lib/Semantics/program-tree.cpp ------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "program-tree.h" 10 #include "flang/Common/idioms.h" 11 #include "flang/Parser/char-block.h" 12 #include "flang/Semantics/scope.h" 13 14 namespace Fortran::semantics { 15 16 template <typename T> 17 static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { 18 const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 19 const auto &exec{std::get<parser::ExecutionPart>(x.t)}; 20 const auto &subps{ 21 std::get<std::optional<parser::InternalSubprogramPart>>(x.t)}; 22 ProgramTree node{name, spec, &exec}; 23 if (subps) { 24 for (const auto &subp : 25 std::get<std::list<parser::InternalSubprogram>>(subps->t)) { 26 std::visit( 27 [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, 28 subp.u); 29 } 30 } 31 return node; 32 } 33 34 static ProgramTree BuildSubprogramTree( 35 const parser::Name &name, const parser::BlockData &x) { 36 const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 37 return ProgramTree{name, spec, nullptr}; 38 } 39 40 template <typename T> 41 static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) { 42 const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 43 const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)}; 44 ProgramTree node{name, spec}; 45 if (subps) { 46 for (const auto &subp : 47 std::get<std::list<parser::ModuleSubprogram>>(subps->t)) { 48 std::visit( 49 [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, 50 subp.u); 51 } 52 } 53 return node; 54 } 55 56 ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) { 57 return std::visit([](const auto &y) { return Build(y.value()); }, x.u); 58 } 59 60 ProgramTree ProgramTree::Build(const parser::MainProgram &x) { 61 const auto &stmt{ 62 std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)}; 63 const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)}; 64 static parser::Name emptyName; 65 auto result{stmt ? BuildSubprogramTree(stmt->statement.v, x).set_stmt(*stmt) 66 : BuildSubprogramTree(emptyName, x)}; 67 return result.set_endStmt(end); 68 } 69 70 ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) { 71 const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)}; 72 const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)}; 73 const auto &name{std::get<parser::Name>(stmt.statement.t)}; 74 return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 75 } 76 77 ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) { 78 const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)}; 79 const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)}; 80 const auto &name{std::get<parser::Name>(stmt.statement.t)}; 81 return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 82 } 83 84 ProgramTree ProgramTree::Build(const parser::SeparateModuleSubprogram &x) { 85 const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)}; 86 const auto &end{ 87 std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)}; 88 const auto &name{stmt.statement.v}; 89 return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 90 } 91 92 ProgramTree ProgramTree::Build(const parser::Module &x) { 93 const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)}; 94 const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)}; 95 const auto &name{stmt.statement.v}; 96 return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); 97 } 98 99 ProgramTree ProgramTree::Build(const parser::Submodule &x) { 100 const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)}; 101 const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)}; 102 const auto &name{std::get<parser::Name>(stmt.statement.t)}; 103 return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); 104 } 105 106 ProgramTree ProgramTree::Build(const parser::BlockData &x) { 107 const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)}; 108 const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)}; 109 static parser::Name emptyName; 110 auto result{stmt.statement.v ? BuildSubprogramTree(*stmt.statement.v, x) 111 : BuildSubprogramTree(emptyName, x)}; 112 return result.set_stmt(stmt).set_endStmt(end); 113 } 114 115 const parser::ParentIdentifier &ProgramTree::GetParentId() const { 116 const auto *stmt{ 117 std::get<const parser::Statement<parser::SubmoduleStmt> *>(stmt_)}; 118 return std::get<parser::ParentIdentifier>(stmt->statement.t); 119 } 120 121 bool ProgramTree::IsModule() const { 122 auto kind{GetKind()}; 123 return kind == Kind::Module || kind == Kind::Submodule; 124 } 125 126 Symbol::Flag ProgramTree::GetSubpFlag() const { 127 return GetKind() == Kind::Function ? Symbol::Flag::Function 128 : Symbol::Flag::Subroutine; 129 } 130 131 bool ProgramTree::HasModulePrefix() const { 132 using ListType = std::list<parser::PrefixSpec>; 133 const auto *prefixes{ 134 std::visit(common::visitors{ 135 [](const parser::Statement<parser::FunctionStmt> *x) { 136 return &std::get<ListType>(x->statement.t); 137 }, 138 [](const parser::Statement<parser::SubroutineStmt> *x) { 139 return &std::get<ListType>(x->statement.t); 140 }, 141 [](const auto *) -> const ListType * { return nullptr; }, 142 }, 143 stmt_)}; 144 if (prefixes) { 145 for (const auto &prefix : *prefixes) { 146 if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) { 147 return true; 148 } 149 } 150 } 151 return false; 152 } 153 154 ProgramTree::Kind ProgramTree::GetKind() const { 155 return std::visit( 156 common::visitors{ 157 [](const parser::Statement<parser::ProgramStmt> *) { 158 return Kind::Program; 159 }, 160 [](const parser::Statement<parser::FunctionStmt> *) { 161 return Kind::Function; 162 }, 163 [](const parser::Statement<parser::SubroutineStmt> *) { 164 return Kind::Subroutine; 165 }, 166 [](const parser::Statement<parser::MpSubprogramStmt> *) { 167 return Kind::MpSubprogram; 168 }, 169 [](const parser::Statement<parser::ModuleStmt> *) { 170 return Kind::Module; 171 }, 172 [](const parser::Statement<parser::SubmoduleStmt> *) { 173 return Kind::Submodule; 174 }, 175 [](const parser::Statement<parser::BlockDataStmt> *) { 176 return Kind::BlockData; 177 }, 178 }, 179 stmt_); 180 } 181 182 void ProgramTree::set_scope(Scope &scope) { 183 scope_ = &scope; 184 CHECK(endStmt_); 185 scope.AddSourceRange(*endStmt_); 186 } 187 188 void ProgramTree::AddChild(ProgramTree &&child) { 189 children_.emplace_back(std::move(child)); 190 } 191 192 } // namespace Fortran::semantics 193