Mercurial > hg > CbC > CbC_llvm
view flang/lib/Semantics/program-tree.cpp @ 207:2e18cbf3894f
LLVM12
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 08 Jun 2021 06:07:14 +0900 |
parents | 0572611fdcc8 |
children | c4bab56944e8 |
line wrap: on
line source
//===-- 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); } ProgramTree ProgramTree::Build(const parser::CompilerDirective &) { DIE("ProgramTree::Build() called for CompilerDirective"); } 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)); } } // namespace Fortran::semantics