// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "program-tree.h" #include "scope.h" #include "../common/idioms.h" #include "../parser/char-block.h" namespace Fortran::semantics { template static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { const auto &spec{std::get(x.t)}; const auto &exec{std::get(x.t)}; const auto &subps{ std::get>(x.t)}; ProgramTree node{name, spec, &exec}; if (subps) { for (const auto &subp : std::get>(subps->t)) { std::visit( [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, subp.u); } } return node; } template static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) { const auto &spec{std::get(x.t)}; const auto &subps{std::get>(x.t)}; ProgramTree node{name, spec}; if (subps) { for (const auto &subp : std::get>(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>>(x.t)}; const auto &end{std::get>(x.t)}; static parser::Name emptyName; const auto &name{stmt ? stmt->statement.v : emptyName}; return BuildSubprogramTree(name, x).set_stmt(*stmt).set_endStmt(end); } ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) { const auto &stmt{std::get>(x.t)}; const auto &end{std::get>(x.t)}; const auto &name{std::get(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>(x.t)}; const auto &end{std::get>(x.t)}; const auto &name{std::get(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>(x.t)}; const auto &end{ std::get>(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>(x.t)}; const auto &end{std::get>(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>(x.t)}; const auto &end{std::get>(x.t)}; const auto &name{std::get(stmt.statement.t)}; return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); } ProgramTree ProgramTree::Build(const parser::BlockData &x) { DIE("BlockData not yet implemented"); } const parser::ParentIdentifier &ProgramTree::GetParentId() const { const auto *stmt{ std::get *>(stmt_)}; return std::get(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; const auto *prefixes{std::visit( common::visitors{ [](const parser::Statement *x) { return &std::get(x->statement.t); }, [](const parser::Statement *x) { return &std::get(x->statement.t); }, [](const auto *) -> const ListType * { return nullptr; }, }, stmt_)}; if (prefixes) { for (const auto &prefix : *prefixes) { if (std::holds_alternative(prefix.u)) { return true; } } } return false; } ProgramTree::Kind ProgramTree::GetKind() const { return std::visit( common::visitors{ [](const parser::Statement *) { return Kind::Program; }, [](const parser::Statement *) { return Kind::Function; }, [](const parser::Statement *) { return Kind::Subroutine; }, [](const parser::Statement *) { return Kind::MpSubprogram; }, [](const parser::Statement *) { return Kind::Module; }, [](const parser::Statement *) { return Kind::Submodule; }, }, 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)); } }