164ab3302SCarolineConcatto //===-- lib/Semantics/program-tree.cpp ------------------------------------===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto #include "program-tree.h" 1064ab3302SCarolineConcatto #include "flang/Common/idioms.h" 1164ab3302SCarolineConcatto #include "flang/Parser/char-block.h" 1264ab3302SCarolineConcatto #include "flang/Semantics/scope.h" 1364ab3302SCarolineConcatto 1464ab3302SCarolineConcatto namespace Fortran::semantics { 1564ab3302SCarolineConcatto 16bed947f7SPeter Klausler static void GetEntryStmts( 17bed947f7SPeter Klausler ProgramTree &node, const parser::SpecificationPart &spec) { 18bed947f7SPeter Klausler const auto &implicitPart{std::get<parser::ImplicitPart>(spec.t)}; 19bed947f7SPeter Klausler for (const parser::ImplicitPartStmt &stmt : implicitPart.v) { 20bed947f7SPeter Klausler if (const auto *entryStmt{std::get_if< 21bed947f7SPeter Klausler parser::Statement<common::Indirection<parser::EntryStmt>>>( 22bed947f7SPeter Klausler &stmt.u)}) { 23bed947f7SPeter Klausler node.AddEntry(entryStmt->statement.value()); 24bed947f7SPeter Klausler } 25bed947f7SPeter Klausler } 26bed947f7SPeter Klausler for (const auto &decl : 27bed947f7SPeter Klausler std::get<std::list<parser::DeclarationConstruct>>(spec.t)) { 28bed947f7SPeter Klausler if (const auto *entryStmt{std::get_if< 29bed947f7SPeter Klausler parser::Statement<common::Indirection<parser::EntryStmt>>>( 30bed947f7SPeter Klausler &decl.u)}) { 31bed947f7SPeter Klausler node.AddEntry(entryStmt->statement.value()); 32bed947f7SPeter Klausler } 33bed947f7SPeter Klausler } 34bed947f7SPeter Klausler } 35bed947f7SPeter Klausler 36bed947f7SPeter Klausler static void GetEntryStmts( 37bed947f7SPeter Klausler ProgramTree &node, const parser::ExecutionPart &exec) { 38bed947f7SPeter Klausler for (const auto &epConstruct : exec.v) { 39bed947f7SPeter Klausler if (const auto *entryStmt{std::get_if< 40bed947f7SPeter Klausler parser::Statement<common::Indirection<parser::EntryStmt>>>( 41bed947f7SPeter Klausler &epConstruct.u)}) { 42bed947f7SPeter Klausler node.AddEntry(entryStmt->statement.value()); 43bed947f7SPeter Klausler } 44bed947f7SPeter Klausler } 45bed947f7SPeter Klausler } 46bed947f7SPeter Klausler 47fc510998SPeter Klausler // Collects generics that define simple names that could include 48fc510998SPeter Klausler // identically-named subprograms as specific procedures. 49fc510998SPeter Klausler static void GetGenerics( 50fc510998SPeter Klausler ProgramTree &node, const parser::SpecificationPart &spec) { 51fc510998SPeter Klausler for (const auto &decl : 52fc510998SPeter Klausler std::get<std::list<parser::DeclarationConstruct>>(spec.t)) { 53fc510998SPeter Klausler if (const auto *spec{ 54fc510998SPeter Klausler std::get_if<parser::SpecificationConstruct>(&decl.u)}) { 55fc510998SPeter Klausler if (const auto *generic{std::get_if< 56fc510998SPeter Klausler parser::Statement<common::Indirection<parser::GenericStmt>>>( 57fc510998SPeter Klausler &spec->u)}) { 58fc510998SPeter Klausler const parser::GenericStmt &genericStmt{generic->statement.value()}; 59fc510998SPeter Klausler const auto &genericSpec{std::get<parser::GenericSpec>(genericStmt.t)}; 60fc510998SPeter Klausler node.AddGeneric(genericSpec); 61fc510998SPeter Klausler } else if (const auto *interface{ 62fc510998SPeter Klausler std::get_if<common::Indirection<parser::InterfaceBlock>>( 63fc510998SPeter Klausler &spec->u)}) { 64fc510998SPeter Klausler const parser::InterfaceBlock &interfaceBlock{interface->value()}; 65fc510998SPeter Klausler const parser::InterfaceStmt &interfaceStmt{ 66fc510998SPeter Klausler std::get<parser::Statement<parser::InterfaceStmt>>(interfaceBlock.t) 67fc510998SPeter Klausler .statement}; 68fc510998SPeter Klausler const auto *genericSpec{ 69fc510998SPeter Klausler std::get_if<std::optional<parser::GenericSpec>>(&interfaceStmt.u)}; 70fc510998SPeter Klausler if (genericSpec && genericSpec->has_value()) { 71fc510998SPeter Klausler node.AddGeneric(**genericSpec); 72fc510998SPeter Klausler } 73fc510998SPeter Klausler } 74fc510998SPeter Klausler } 75fc510998SPeter Klausler } 76fc510998SPeter Klausler } 77fc510998SPeter Klausler 7864ab3302SCarolineConcatto template <typename T> 7964ab3302SCarolineConcatto static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { 8064ab3302SCarolineConcatto const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 8164ab3302SCarolineConcatto const auto &exec{std::get<parser::ExecutionPart>(x.t)}; 8264ab3302SCarolineConcatto const auto &subps{ 8364ab3302SCarolineConcatto std::get<std::optional<parser::InternalSubprogramPart>>(x.t)}; 8464ab3302SCarolineConcatto ProgramTree node{name, spec, &exec}; 85bed947f7SPeter Klausler GetEntryStmts(node, spec); 86bed947f7SPeter Klausler GetEntryStmts(node, exec); 87fc510998SPeter Klausler GetGenerics(node, spec); 8864ab3302SCarolineConcatto if (subps) { 8964ab3302SCarolineConcatto for (const auto &subp : 9064ab3302SCarolineConcatto std::get<std::list<parser::InternalSubprogram>>(subps->t)) { 91*cd03e96fSPeter Klausler common::visit( 9264ab3302SCarolineConcatto [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, 9364ab3302SCarolineConcatto subp.u); 9464ab3302SCarolineConcatto } 9564ab3302SCarolineConcatto } 9664ab3302SCarolineConcatto return node; 9764ab3302SCarolineConcatto } 9864ab3302SCarolineConcatto 9964ab3302SCarolineConcatto static ProgramTree BuildSubprogramTree( 10064ab3302SCarolineConcatto const parser::Name &name, const parser::BlockData &x) { 10164ab3302SCarolineConcatto const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 102bed947f7SPeter Klausler return ProgramTree{name, spec}; 10364ab3302SCarolineConcatto } 10464ab3302SCarolineConcatto 10564ab3302SCarolineConcatto template <typename T> 10664ab3302SCarolineConcatto static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) { 10764ab3302SCarolineConcatto const auto &spec{std::get<parser::SpecificationPart>(x.t)}; 10864ab3302SCarolineConcatto const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)}; 10964ab3302SCarolineConcatto ProgramTree node{name, spec}; 110fc510998SPeter Klausler GetGenerics(node, spec); 11164ab3302SCarolineConcatto if (subps) { 11264ab3302SCarolineConcatto for (const auto &subp : 11364ab3302SCarolineConcatto std::get<std::list<parser::ModuleSubprogram>>(subps->t)) { 114*cd03e96fSPeter Klausler common::visit( 11564ab3302SCarolineConcatto [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, 11664ab3302SCarolineConcatto subp.u); 11764ab3302SCarolineConcatto } 11864ab3302SCarolineConcatto } 11964ab3302SCarolineConcatto return node; 12064ab3302SCarolineConcatto } 12164ab3302SCarolineConcatto 12264ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) { 123*cd03e96fSPeter Klausler return common::visit([](const auto &y) { return Build(y.value()); }, x.u); 12464ab3302SCarolineConcatto } 12564ab3302SCarolineConcatto 12664ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::MainProgram &x) { 12764ab3302SCarolineConcatto const auto &stmt{ 12864ab3302SCarolineConcatto std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)}; 12964ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)}; 13064ab3302SCarolineConcatto static parser::Name emptyName; 13164ab3302SCarolineConcatto auto result{stmt ? BuildSubprogramTree(stmt->statement.v, x).set_stmt(*stmt) 13264ab3302SCarolineConcatto : BuildSubprogramTree(emptyName, x)}; 13364ab3302SCarolineConcatto return result.set_endStmt(end); 13464ab3302SCarolineConcatto } 13564ab3302SCarolineConcatto 13664ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) { 13764ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)}; 13864ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)}; 13964ab3302SCarolineConcatto const auto &name{std::get<parser::Name>(stmt.statement.t)}; 14064ab3302SCarolineConcatto return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 14164ab3302SCarolineConcatto } 14264ab3302SCarolineConcatto 14364ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) { 14464ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)}; 14564ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)}; 14664ab3302SCarolineConcatto const auto &name{std::get<parser::Name>(stmt.statement.t)}; 14764ab3302SCarolineConcatto return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 14864ab3302SCarolineConcatto } 14964ab3302SCarolineConcatto 15064ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::SeparateModuleSubprogram &x) { 15164ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)}; 15264ab3302SCarolineConcatto const auto &end{ 15364ab3302SCarolineConcatto std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)}; 15464ab3302SCarolineConcatto const auto &name{stmt.statement.v}; 15564ab3302SCarolineConcatto return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); 15664ab3302SCarolineConcatto } 15764ab3302SCarolineConcatto 15864ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::Module &x) { 15964ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)}; 16064ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)}; 16164ab3302SCarolineConcatto const auto &name{stmt.statement.v}; 16264ab3302SCarolineConcatto return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); 16364ab3302SCarolineConcatto } 16464ab3302SCarolineConcatto 16564ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::Submodule &x) { 16664ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)}; 16764ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)}; 16864ab3302SCarolineConcatto const auto &name{std::get<parser::Name>(stmt.statement.t)}; 16964ab3302SCarolineConcatto return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); 17064ab3302SCarolineConcatto } 17164ab3302SCarolineConcatto 17264ab3302SCarolineConcatto ProgramTree ProgramTree::Build(const parser::BlockData &x) { 17364ab3302SCarolineConcatto const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)}; 17464ab3302SCarolineConcatto const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)}; 17564ab3302SCarolineConcatto static parser::Name emptyName; 17664ab3302SCarolineConcatto auto result{stmt.statement.v ? BuildSubprogramTree(*stmt.statement.v, x) 17764ab3302SCarolineConcatto : BuildSubprogramTree(emptyName, x)}; 17864ab3302SCarolineConcatto return result.set_stmt(stmt).set_endStmt(end); 17964ab3302SCarolineConcatto } 18064ab3302SCarolineConcatto 18113cee14bSpeter klausler ProgramTree ProgramTree::Build(const parser::CompilerDirective &) { 18213cee14bSpeter klausler DIE("ProgramTree::Build() called for CompilerDirective"); 18313cee14bSpeter klausler } 18413cee14bSpeter klausler 18564ab3302SCarolineConcatto const parser::ParentIdentifier &ProgramTree::GetParentId() const { 18664ab3302SCarolineConcatto const auto *stmt{ 18764ab3302SCarolineConcatto std::get<const parser::Statement<parser::SubmoduleStmt> *>(stmt_)}; 18864ab3302SCarolineConcatto return std::get<parser::ParentIdentifier>(stmt->statement.t); 18964ab3302SCarolineConcatto } 19064ab3302SCarolineConcatto 19164ab3302SCarolineConcatto bool ProgramTree::IsModule() const { 19264ab3302SCarolineConcatto auto kind{GetKind()}; 19364ab3302SCarolineConcatto return kind == Kind::Module || kind == Kind::Submodule; 19464ab3302SCarolineConcatto } 19564ab3302SCarolineConcatto 19664ab3302SCarolineConcatto Symbol::Flag ProgramTree::GetSubpFlag() const { 19764ab3302SCarolineConcatto return GetKind() == Kind::Function ? Symbol::Flag::Function 19864ab3302SCarolineConcatto : Symbol::Flag::Subroutine; 19964ab3302SCarolineConcatto } 20064ab3302SCarolineConcatto 20164ab3302SCarolineConcatto bool ProgramTree::HasModulePrefix() const { 20264ab3302SCarolineConcatto using ListType = std::list<parser::PrefixSpec>; 203*cd03e96fSPeter Klausler const auto *prefixes{common::visit( 204*cd03e96fSPeter Klausler common::visitors{ 20564ab3302SCarolineConcatto [](const parser::Statement<parser::FunctionStmt> *x) { 20664ab3302SCarolineConcatto return &std::get<ListType>(x->statement.t); 20764ab3302SCarolineConcatto }, 20864ab3302SCarolineConcatto [](const parser::Statement<parser::SubroutineStmt> *x) { 20964ab3302SCarolineConcatto return &std::get<ListType>(x->statement.t); 21064ab3302SCarolineConcatto }, 21164ab3302SCarolineConcatto [](const auto *) -> const ListType * { return nullptr; }, 21264ab3302SCarolineConcatto }, 21364ab3302SCarolineConcatto stmt_)}; 21464ab3302SCarolineConcatto if (prefixes) { 21564ab3302SCarolineConcatto for (const auto &prefix : *prefixes) { 21664ab3302SCarolineConcatto if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) { 21764ab3302SCarolineConcatto return true; 21864ab3302SCarolineConcatto } 21964ab3302SCarolineConcatto } 22064ab3302SCarolineConcatto } 22164ab3302SCarolineConcatto return false; 22264ab3302SCarolineConcatto } 22364ab3302SCarolineConcatto 22464ab3302SCarolineConcatto ProgramTree::Kind ProgramTree::GetKind() const { 225*cd03e96fSPeter Klausler return common::visit( 22664ab3302SCarolineConcatto common::visitors{ 22764ab3302SCarolineConcatto [](const parser::Statement<parser::ProgramStmt> *) { 22864ab3302SCarolineConcatto return Kind::Program; 22964ab3302SCarolineConcatto }, 23064ab3302SCarolineConcatto [](const parser::Statement<parser::FunctionStmt> *) { 23164ab3302SCarolineConcatto return Kind::Function; 23264ab3302SCarolineConcatto }, 23364ab3302SCarolineConcatto [](const parser::Statement<parser::SubroutineStmt> *) { 23464ab3302SCarolineConcatto return Kind::Subroutine; 23564ab3302SCarolineConcatto }, 23664ab3302SCarolineConcatto [](const parser::Statement<parser::MpSubprogramStmt> *) { 23764ab3302SCarolineConcatto return Kind::MpSubprogram; 23864ab3302SCarolineConcatto }, 23964ab3302SCarolineConcatto [](const parser::Statement<parser::ModuleStmt> *) { 24064ab3302SCarolineConcatto return Kind::Module; 24164ab3302SCarolineConcatto }, 24264ab3302SCarolineConcatto [](const parser::Statement<parser::SubmoduleStmt> *) { 24364ab3302SCarolineConcatto return Kind::Submodule; 24464ab3302SCarolineConcatto }, 24564ab3302SCarolineConcatto [](const parser::Statement<parser::BlockDataStmt> *) { 24664ab3302SCarolineConcatto return Kind::BlockData; 24764ab3302SCarolineConcatto }, 24864ab3302SCarolineConcatto }, 24964ab3302SCarolineConcatto stmt_); 25064ab3302SCarolineConcatto } 25164ab3302SCarolineConcatto 25264ab3302SCarolineConcatto void ProgramTree::set_scope(Scope &scope) { 25364ab3302SCarolineConcatto scope_ = &scope; 25464ab3302SCarolineConcatto CHECK(endStmt_); 25564ab3302SCarolineConcatto scope.AddSourceRange(*endStmt_); 25664ab3302SCarolineConcatto } 25764ab3302SCarolineConcatto 25864ab3302SCarolineConcatto void ProgramTree::AddChild(ProgramTree &&child) { 25964ab3302SCarolineConcatto children_.emplace_back(std::move(child)); 26064ab3302SCarolineConcatto } 26164ab3302SCarolineConcatto 262bed947f7SPeter Klausler void ProgramTree::AddEntry(const parser::EntryStmt &entryStmt) { 263bed947f7SPeter Klausler entryStmts_.emplace_back(entryStmt); 264bed947f7SPeter Klausler } 265bed947f7SPeter Klausler 266fc510998SPeter Klausler void ProgramTree::AddGeneric(const parser::GenericSpec &generic) { 267fc510998SPeter Klausler genericSpecs_.emplace_back(generic); 268fc510998SPeter Klausler } 269fc510998SPeter Klausler 2701f879005STim Keith } // namespace Fortran::semantics 271