//===-- lib/Semantics/program-tree.h ----------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_ #define FORTRAN_SEMANTICS_PROGRAM_TREE_H_ #include "flang/Parser/parse-tree.h" #include "flang/Semantics/symbol.h" #include #include // A ProgramTree represents a tree of program units and their contained // subprograms. The root nodes represent: main program, function, subroutine, // module subprogram, module, or submodule. // Each node of the tree consists of: // - the statement that introduces the program unit // - the specification part // - the execution part if applicable (not for module or submodule) // - a child node for each contained subprogram namespace Fortran::semantics { class Scope; class ProgramTree { public: // Build the ProgramTree rooted at one of these program units. static ProgramTree Build(const parser::ProgramUnit &); static ProgramTree Build(const parser::MainProgram &); static ProgramTree Build(const parser::FunctionSubprogram &); static ProgramTree Build(const parser::SubroutineSubprogram &); static ProgramTree Build(const parser::SeparateModuleSubprogram &); static ProgramTree Build(const parser::Module &); static ProgramTree Build(const parser::Submodule &); static ProgramTree Build(const parser::BlockData &); static ProgramTree Build(const parser::CompilerDirective &); ENUM_CLASS(Kind, // kind of node Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData) using Stmt = std::variant< // the statement that introduces the program unit const parser::Statement *, const parser::Statement *, const parser::Statement *, const parser::Statement *, const parser::Statement *, const parser::Statement *, const parser::Statement *>; ProgramTree(const parser::Name &name, const parser::SpecificationPart &spec, const parser::ExecutionPart *exec = nullptr) : name_{name}, spec_{spec}, exec_{exec} {} const parser::Name &name() const { return name_; } Kind GetKind() const; const Stmt &stmt() const { return stmt_; } bool isSpecificationPartResolved() const { return isSpecificationPartResolved_; } void set_isSpecificationPartResolved(bool yes = true) { isSpecificationPartResolved_ = yes; } const parser::ParentIdentifier &GetParentId() const; // only for Submodule const parser::SpecificationPart &spec() const { return spec_; } const parser::ExecutionPart *exec() const { return exec_; } std::list &children() { return children_; } const std::list &children() const { return children_; } Symbol::Flag GetSubpFlag() const; bool IsModule() const; // Module or Submodule bool HasModulePrefix() const; // in function or subroutine stmt Scope *scope() const { return scope_; } void set_scope(Scope &); void AddChild(ProgramTree &&); template ProgramTree &set_stmt(const parser::Statement &stmt) { stmt_ = &stmt; return *this; } template ProgramTree &set_endStmt(const parser::Statement &stmt) { endStmt_ = &stmt.source; return *this; } private: const parser::Name &name_; Stmt stmt_{ static_cast *>(nullptr)}; const parser::SpecificationPart &spec_; const parser::ExecutionPart *exec_{nullptr}; std::list children_; Scope *scope_{nullptr}; const parser::CharBlock *endStmt_{nullptr}; bool isSpecificationPartResolved_{false}; }; } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_PROGRAM_TREE_H_