1 //===-- lib/Semantics/program-tree.h ----------------------------*- C++ -*-===// 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 #ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_ 10 #define FORTRAN_SEMANTICS_PROGRAM_TREE_H_ 11 12 #include "flang/Parser/parse-tree.h" 13 #include "flang/Semantics/symbol.h" 14 #include <list> 15 #include <variant> 16 17 // A ProgramTree represents a tree of program units and their contained 18 // subprograms. The root nodes represent: main program, function, subroutine, 19 // module subprogram, module, or submodule. 20 // Each node of the tree consists of: 21 // - the statement that introduces the program unit 22 // - the specification part 23 // - the execution part if applicable (not for module or submodule) 24 // - a child node for each contained subprogram 25 26 namespace Fortran::semantics { 27 28 class Scope; 29 30 class ProgramTree { 31 public: 32 using EntryStmtList = std::list<common::Reference<const parser::EntryStmt>>; 33 using GenericSpecList = 34 std::list<common::Reference<const parser::GenericSpec>>; 35 36 // Build the ProgramTree rooted at one of these program units. 37 static ProgramTree Build(const parser::ProgramUnit &); 38 static ProgramTree Build(const parser::MainProgram &); 39 static ProgramTree Build(const parser::FunctionSubprogram &); 40 static ProgramTree Build(const parser::SubroutineSubprogram &); 41 static ProgramTree Build(const parser::SeparateModuleSubprogram &); 42 static ProgramTree Build(const parser::Module &); 43 static ProgramTree Build(const parser::Submodule &); 44 static ProgramTree Build(const parser::BlockData &); 45 static ProgramTree Build(const parser::CompilerDirective &); 46 47 ENUM_CLASS(Kind, // kind of node 48 Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData) 49 using Stmt = std::variant< // the statement that introduces the program unit 50 const parser::Statement<parser::ProgramStmt> *, 51 const parser::Statement<parser::FunctionStmt> *, 52 const parser::Statement<parser::SubroutineStmt> *, 53 const parser::Statement<parser::MpSubprogramStmt> *, 54 const parser::Statement<parser::ModuleStmt> *, 55 const parser::Statement<parser::SubmoduleStmt> *, 56 const parser::Statement<parser::BlockDataStmt> *>; 57 58 ProgramTree(const parser::Name &name, const parser::SpecificationPart &spec, 59 const parser::ExecutionPart *exec = nullptr) 60 : name_{name}, spec_{spec}, exec_{exec} {} 61 name()62 const parser::Name &name() const { return name_; } 63 Kind GetKind() const; stmt()64 const Stmt &stmt() const { return stmt_; } isSpecificationPartResolved()65 bool isSpecificationPartResolved() const { 66 return isSpecificationPartResolved_; 67 } 68 void set_isSpecificationPartResolved(bool yes = true) { 69 isSpecificationPartResolved_ = yes; 70 } 71 const parser::ParentIdentifier &GetParentId() const; // only for Submodule spec()72 const parser::SpecificationPart &spec() const { return spec_; } exec()73 const parser::ExecutionPart *exec() const { return exec_; } children()74 std::list<ProgramTree> &children() { return children_; } children()75 const std::list<ProgramTree> &children() const { return children_; } entryStmts()76 const EntryStmtList &entryStmts() const { return entryStmts_; } genericSpecs()77 const GenericSpecList &genericSpecs() const { return genericSpecs_; } 78 79 Symbol::Flag GetSubpFlag() const; 80 bool IsModule() const; // Module or Submodule 81 bool HasModulePrefix() const; // in function or subroutine stmt scope()82 Scope *scope() const { return scope_; } 83 void set_scope(Scope &); bindingSpec()84 const parser::LanguageBindingSpec *bindingSpec() const { 85 return bindingSpec_; 86 } set_bindingSpec(const parser::LanguageBindingSpec * spec)87 ProgramTree &set_bindingSpec(const parser::LanguageBindingSpec *spec) { 88 bindingSpec_ = spec; 89 return *this; 90 } 91 void AddChild(ProgramTree &&); 92 void AddEntry(const parser::EntryStmt &); 93 void AddGeneric(const parser::GenericSpec &); 94 95 template <typename T> set_stmt(const parser::Statement<T> & stmt)96 ProgramTree &set_stmt(const parser::Statement<T> &stmt) { 97 stmt_ = &stmt; 98 return *this; 99 } 100 template <typename T> set_endStmt(const parser::Statement<T> & stmt)101 ProgramTree &set_endStmt(const parser::Statement<T> &stmt) { 102 endStmt_ = &stmt.source; 103 return *this; 104 } 105 106 private: 107 const parser::Name &name_; 108 Stmt stmt_{ 109 static_cast<const parser::Statement<parser::ProgramStmt> *>(nullptr)}; 110 const parser::SpecificationPart &spec_; 111 const parser::ExecutionPart *exec_{nullptr}; 112 std::list<ProgramTree> children_; 113 EntryStmtList entryStmts_; 114 GenericSpecList genericSpecs_; 115 Scope *scope_{nullptr}; 116 const parser::CharBlock *endStmt_{nullptr}; 117 bool isSpecificationPartResolved_{false}; 118 const parser::LanguageBindingSpec *bindingSpec_{nullptr}; 119 }; 120 121 } // namespace Fortran::semantics 122 #endif // FORTRAN_SEMANTICS_PROGRAM_TREE_H_ 123