1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
//===-- 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 <list>
#include <variant>
// 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 SemanticsContext;
class ProgramTree {
public:
using EntryStmtList = std::list<common::Reference<const parser::EntryStmt>>;
using GenericSpecList =
std::list<common::Reference<const parser::GenericSpec>>;
// Build the ProgramTree rooted at one of these program units.
static ProgramTree Build(const parser::ProgramUnit &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::MainProgram &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::FunctionSubprogram &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::SubroutineSubprogram &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::SeparateModuleSubprogram &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::Module &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::Submodule &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::BlockData &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::CompilerDirective &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::OpenACCRoutineConstruct &, SemanticsContext &);
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<parser::ProgramStmt> *,
const parser::Statement<parser::FunctionStmt> *,
const parser::Statement<parser::SubroutineStmt> *,
const parser::Statement<parser::MpSubprogramStmt> *,
const parser::Statement<parser::ModuleStmt> *,
const parser::Statement<parser::SubmoduleStmt> *,
const parser::Statement<parser::BlockDataStmt> *>;
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<ProgramTree> &children() { return children_; }
const std::list<ProgramTree> &children() const { return children_; }
const EntryStmtList &entryStmts() const { return entryStmts_; }
const GenericSpecList &genericSpecs() const { return genericSpecs_; }
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 &);
const parser::LanguageBindingSpec *bindingSpec() const {
return bindingSpec_;
}
ProgramTree &set_bindingSpec(const parser::LanguageBindingSpec *spec) {
bindingSpec_ = spec;
return *this;
}
void AddChild(ProgramTree &&);
void AddEntry(const parser::EntryStmt &);
void AddGeneric(const parser::GenericSpec &);
template <typename T>
ProgramTree &set_stmt(const parser::Statement<T> &stmt) {
stmt_ = &stmt;
return *this;
}
template <typename T>
ProgramTree &set_endStmt(const parser::Statement<T> &stmt) {
endStmt_ = &stmt.source;
return *this;
}
private:
const parser::Name &name_;
Stmt stmt_{
static_cast<const parser::Statement<parser::ProgramStmt> *>(nullptr)};
const parser::SpecificationPart &spec_;
const parser::ExecutionPart *exec_{nullptr};
std::list<ProgramTree> children_;
EntryStmtList entryStmts_;
GenericSpecList genericSpecs_;
Scope *scope_{nullptr};
const parser::CharBlock *endStmt_{nullptr};
bool isSpecificationPartResolved_{false};
const parser::LanguageBindingSpec *bindingSpec_{nullptr};
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_PROGRAM_TREE_H_
|