2020-02-25 23:11:52 +08:00
|
|
|
//===-- lib/Semantics/program-tree.h ----------------------------*- C++ -*-===//
|
2019-05-07 01:12:27 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// 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
|
2019-05-07 01:12:27 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-05-07 01:12:27 +08:00
|
|
|
|
|
|
|
#ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_
|
|
|
|
#define FORTRAN_SEMANTICS_PROGRAM_TREE_H_
|
|
|
|
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Parser/parse-tree.h"
|
|
|
|
#include "flang/Semantics/symbol.h"
|
2020-03-14 03:19:44 +08:00
|
|
|
#include <list>
|
2019-05-07 01:12:27 +08:00
|
|
|
#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 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 &);
|
2020-08-26 00:39:52 +08:00
|
|
|
static ProgramTree Build(const parser::CompilerDirective &);
|
2019-05-07 01:12:27 +08:00
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
ENUM_CLASS(Kind, // kind of node
|
2020-01-10 09:12:46 +08:00
|
|
|
Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData)
|
2020-03-29 12:00:16 +08:00
|
|
|
using Stmt = std::variant< // the statement that introduces the program unit
|
2019-05-07 01:12:27 +08:00
|
|
|
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> *,
|
2020-01-10 09:12:46 +08:00
|
|
|
const parser::Statement<parser::SubmoduleStmt> *,
|
|
|
|
const parser::Statement<parser::BlockDataStmt> *>;
|
2019-05-07 01:12:27 +08:00
|
|
|
|
|
|
|
ProgramTree(const parser::Name &name, const parser::SpecificationPart &spec,
|
|
|
|
const parser::ExecutionPart *exec = nullptr)
|
2020-03-29 12:00:16 +08:00
|
|
|
: name_{name}, spec_{spec}, exec_{exec} {}
|
2019-05-07 01:12:27 +08:00
|
|
|
|
|
|
|
const parser::Name &name() const { return name_; }
|
|
|
|
Kind GetKind() const;
|
|
|
|
const Stmt &stmt() const { return stmt_; }
|
2020-03-14 03:19:44 +08:00
|
|
|
bool isSpecificationPartResolved() const {
|
|
|
|
return isSpecificationPartResolved_;
|
|
|
|
}
|
|
|
|
void set_isSpecificationPartResolved(bool yes = true) {
|
|
|
|
isSpecificationPartResolved_ = yes;
|
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
const parser::ParentIdentifier &GetParentId() const; // only for Submodule
|
2019-05-07 01:12:27 +08:00
|
|
|
const parser::SpecificationPart &spec() const { return spec_; }
|
|
|
|
const parser::ExecutionPart *exec() const { return exec_; }
|
2020-03-14 03:19:44 +08:00
|
|
|
std::list<ProgramTree> &children() { return children_; }
|
|
|
|
const std::list<ProgramTree> &children() const { return children_; }
|
2019-05-07 01:12:27 +08:00
|
|
|
Symbol::Flag GetSubpFlag() const;
|
2020-03-29 12:00:16 +08:00
|
|
|
bool IsModule() const; // Module or Submodule
|
|
|
|
bool HasModulePrefix() const; // in function or subroutine stmt
|
2019-05-07 01:12:27 +08:00
|
|
|
Scope *scope() const { return scope_; }
|
|
|
|
void set_scope(Scope &);
|
|
|
|
void AddChild(ProgramTree &&);
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T>
|
|
|
|
ProgramTree &set_stmt(const parser::Statement<T> &stmt) {
|
2019-05-07 01:12:27 +08:00
|
|
|
stmt_ = &stmt;
|
|
|
|
return *this;
|
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T>
|
2019-05-07 01:12:27 +08:00
|
|
|
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};
|
2020-03-14 03:19:44 +08:00
|
|
|
std::list<ProgramTree> children_;
|
2019-05-07 01:12:27 +08:00
|
|
|
Scope *scope_{nullptr};
|
|
|
|
const parser::CharBlock *endStmt_{nullptr};
|
2020-03-14 03:19:44 +08:00
|
|
|
bool isSpecificationPartResolved_{false};
|
2019-05-07 01:12:27 +08:00
|
|
|
};
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::semantics
|
|
|
|
#endif // FORTRAN_SEMANTICS_PROGRAM_TREE_H_
|