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