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 ProgramTree ProgramTree::Build(const parser::CompilerDirective &) { 116 DIE("ProgramTree::Build() called for CompilerDirective"); 117 } 118 119 const parser::ParentIdentifier &ProgramTree::GetParentId() const { 120 const auto *stmt{ 121 std::get<const parser::Statement<parser::SubmoduleStmt> *>(stmt_)}; 122 return std::get<parser::ParentIdentifier>(stmt->statement.t); 123 } 124 125 bool ProgramTree::IsModule() const { 126 auto kind{GetKind()}; 127 return kind == Kind::Module || kind == Kind::Submodule; 128 } 129 130 Symbol::Flag ProgramTree::GetSubpFlag() const { 131 return GetKind() == Kind::Function ? Symbol::Flag::Function 132 : Symbol::Flag::Subroutine; 133 } 134 135 bool ProgramTree::HasModulePrefix() const { 136 using ListType = std::list<parser::PrefixSpec>; 137 const auto *prefixes{ 138 std::visit(common::visitors{ 139 [](const parser::Statement<parser::FunctionStmt> *x) { 140 return &std::get<ListType>(x->statement.t); 141 }, 142 [](const parser::Statement<parser::SubroutineStmt> *x) { 143 return &std::get<ListType>(x->statement.t); 144 }, 145 [](const auto *) -> const ListType * { return nullptr; }, 146 }, 147 stmt_)}; 148 if (prefixes) { 149 for (const auto &prefix : *prefixes) { 150 if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) { 151 return true; 152 } 153 } 154 } 155 return false; 156 } 157 158 ProgramTree::Kind ProgramTree::GetKind() const { 159 return std::visit( 160 common::visitors{ 161 [](const parser::Statement<parser::ProgramStmt> *) { 162 return Kind::Program; 163 }, 164 [](const parser::Statement<parser::FunctionStmt> *) { 165 return Kind::Function; 166 }, 167 [](const parser::Statement<parser::SubroutineStmt> *) { 168 return Kind::Subroutine; 169 }, 170 [](const parser::Statement<parser::MpSubprogramStmt> *) { 171 return Kind::MpSubprogram; 172 }, 173 [](const parser::Statement<parser::ModuleStmt> *) { 174 return Kind::Module; 175 }, 176 [](const parser::Statement<parser::SubmoduleStmt> *) { 177 return Kind::Submodule; 178 }, 179 [](const parser::Statement<parser::BlockDataStmt> *) { 180 return Kind::BlockData; 181 }, 182 }, 183 stmt_); 184 } 185 186 void ProgramTree::set_scope(Scope &scope) { 187 scope_ = &scope; 188 CHECK(endStmt_); 189 scope.AddSourceRange(*endStmt_); 190 } 191 192 void ProgramTree::AddChild(ProgramTree &&child) { 193 children_.emplace_back(std::move(child)); 194 } 195 196 } // namespace Fortran::semantics 197