2018-03-23 01:08:20 +01:00
|
|
|
#ifndef FORTRAN_SEMANTICS_SCOPE_H_
|
|
|
|
#define FORTRAN_SEMANTICS_SCOPE_H_
|
|
|
|
|
|
|
|
#include "../parser/idioms.h"
|
2018-03-23 20:24:29 +01:00
|
|
|
#include "../parser/parse-tree.h"
|
2018-03-23 01:08:20 +01:00
|
|
|
#include "attr.h"
|
|
|
|
#include "symbol.h"
|
|
|
|
#include <list>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
namespace Fortran::semantics {
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
class Scope {
|
|
|
|
public:
|
|
|
|
// root of the scope tree; contains intrinsics:
|
|
|
|
static const Scope systemScope;
|
|
|
|
static Scope globalScope; // contains program-units
|
|
|
|
|
|
|
|
enum class Kind {
|
|
|
|
System,
|
|
|
|
Global,
|
|
|
|
Module,
|
|
|
|
MainProgram,
|
|
|
|
Subprogram,
|
|
|
|
};
|
|
|
|
|
|
|
|
Scope(const Scope &parent, Kind kind) : parent_{parent}, kind_{kind} {}
|
|
|
|
|
|
|
|
const Scope &parent() const {
|
|
|
|
CHECK(kind_ != Kind::System);
|
|
|
|
return parent_;
|
|
|
|
}
|
|
|
|
Kind kind() const { return kind_; }
|
|
|
|
|
|
|
|
/// Make a scope nested in this one
|
|
|
|
Scope &MakeScope(Kind kind);
|
|
|
|
|
|
|
|
/// If there is a symbol with this name already in the scope, return it.
|
|
|
|
/// Otherwise make a new one and return that.
|
2018-03-23 20:24:29 +01:00
|
|
|
Symbol &GetOrMakeSymbol(const parser::Name &name);
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
/// Make a Symbol with unknown details.
|
2018-03-23 20:24:29 +01:00
|
|
|
Symbol &MakeSymbol(
|
|
|
|
const parser::Name &name, const Attrs &attrs = Attrs::EMPTY);
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
/// Make a Symbol with provided details.
|
2018-03-23 20:24:29 +01:00
|
|
|
template<typename D>
|
|
|
|
Symbol &MakeSymbol(const parser::Name &name, D &&details) {
|
2018-03-23 01:08:20 +01:00
|
|
|
const auto &result =
|
|
|
|
symbols_.try_emplace(name, *this, name, Attrs::EMPTY, details);
|
|
|
|
return result.first->second;
|
|
|
|
}
|
|
|
|
template<typename D>
|
2018-03-23 20:24:29 +01:00
|
|
|
Symbol &MakeSymbol(
|
|
|
|
const parser::Name &name, const Attrs &attrs, D &&details) {
|
2018-03-23 01:08:20 +01:00
|
|
|
const auto &result =
|
|
|
|
symbols_.try_emplace(name, *this, name, attrs, details);
|
|
|
|
return result.first->second;
|
|
|
|
}
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
void EraseSymbol(const parser::Name &name) {
|
|
|
|
symbols_.erase(name);
|
|
|
|
}
|
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
private:
|
|
|
|
const Scope &parent_;
|
|
|
|
const Kind kind_;
|
|
|
|
std::list<Scope> children_;
|
2018-03-23 20:24:29 +01:00
|
|
|
std::map<parser::Name, Symbol> symbols_;
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
friend std::ostream &operator<<(std::ostream &, const Scope &);
|
|
|
|
};
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
} // namespace Fortran::semantics
|
2018-03-23 01:08:20 +01:00
|
|
|
#endif // FORTRAN_SEMANTICS_SCOPE_H_
|