7edb7ec69b
Refactor to create the Semantics class that is responsible for holding state during semantics (the scope tree and messages) and managing the logic of the various phases of semantic processing. Eliminate static Scope::globalScope. The messages generated during semantic processing are accumulated in a Messages data member of Semantics so that individual phases don't need to emit them to std::cerr. This is now done by the driver so that it has control over where they go and eliminates other includes of iostream. To do this, the messages object is passed in to the various semantics operations. Move DumpSymbols into semantics.cc: it doesn't belong in resolve-names.cc and it depends on the global scope, so it's as good a place as any. The call to RewriteParseTree is also moved to Semantics. Original-commit: flang-compiler/f18@771d0e1293 Reviewed-on: https://github.com/flang-compiler/f18/pull/186 Tree-same-pre-rewrite: false
162 lines
5.4 KiB
C++
162 lines
5.4 KiB
C++
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef FORTRAN_SEMANTICS_SCOPE_H_
|
|
#define FORTRAN_SEMANTICS_SCOPE_H_
|
|
|
|
#include "attr.h"
|
|
#include "symbol.h"
|
|
#include "../common/fortran.h"
|
|
#include "../common/idioms.h"
|
|
#include "../parser/message.h"
|
|
#include <list>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
namespace Fortran::semantics {
|
|
|
|
using namespace parser::literals;
|
|
|
|
class Scope {
|
|
using mapType = std::map<SourceName, Symbol *>;
|
|
|
|
public:
|
|
ENUM_CLASS(
|
|
Kind, System, Global, Module, MainProgram, Subprogram, DerivedType, Block)
|
|
using ImportKind = common::ImportKind;
|
|
|
|
// Create the Global scope -- the root of the scope tree
|
|
Scope() : Scope{*this, Kind::Global, nullptr} {}
|
|
Scope(Scope &parent, Kind kind, Symbol *symbol)
|
|
: parent_{parent}, kind_{kind}, symbol_{symbol} {
|
|
if (symbol) {
|
|
symbol->set_scope(this);
|
|
}
|
|
}
|
|
|
|
bool operator==(const Scope &that) const { return this == &that; }
|
|
bool operator!=(const Scope &that) const { return this != &that; }
|
|
|
|
Scope &parent() {
|
|
CHECK(kind_ != Kind::System);
|
|
return parent_;
|
|
}
|
|
const Scope &parent() const {
|
|
CHECK(kind_ != Kind::System);
|
|
return parent_;
|
|
}
|
|
Kind kind() const { return kind_; }
|
|
bool IsModule() const; // only module, not submodule
|
|
Symbol *symbol() { return symbol_; }
|
|
const Symbol *symbol() const { return symbol_; }
|
|
|
|
const SourceName &name() const {
|
|
CHECK(symbol_); // must only be called for Scopes known to have a symbol
|
|
return symbol_->name();
|
|
}
|
|
|
|
/// Make a scope nested in this one
|
|
Scope &MakeScope(Kind kind, Symbol *symbol = nullptr);
|
|
|
|
using size_type = mapType::size_type;
|
|
using iterator = mapType::iterator;
|
|
using const_iterator = mapType::const_iterator;
|
|
|
|
iterator begin() { return symbols_.begin(); }
|
|
iterator end() { return symbols_.end(); }
|
|
const_iterator begin() const { return symbols_.begin(); }
|
|
const_iterator end() const { return symbols_.end(); }
|
|
const_iterator cbegin() const { return symbols_.cbegin(); }
|
|
const_iterator cend() const { return symbols_.cend(); }
|
|
|
|
iterator find(const SourceName &name);
|
|
const_iterator find(const SourceName &name) const;
|
|
size_type erase(const SourceName &);
|
|
size_type size() const { return symbols_.size(); }
|
|
|
|
// Look for symbol by name in this scope and host (depending on imports).
|
|
Symbol *FindSymbol(const SourceName &);
|
|
|
|
/// Make a Symbol with unknown details.
|
|
std::pair<iterator, bool> try_emplace(
|
|
const SourceName &name, Attrs attrs = Attrs()) {
|
|
return try_emplace(name, attrs, UnknownDetails());
|
|
}
|
|
/// Make a Symbol with provided details.
|
|
template<typename D>
|
|
std::pair<iterator, bool> try_emplace(const SourceName &name, D &&details) {
|
|
return try_emplace(name, Attrs(), details);
|
|
}
|
|
/// Make a Symbol with attrs and details
|
|
template<typename D>
|
|
std::pair<iterator, bool> try_emplace(
|
|
const SourceName &name, Attrs attrs, D &&details) {
|
|
Symbol &symbol{MakeSymbol(name, attrs, std::move(details))};
|
|
return symbols_.emplace(name, &symbol);
|
|
}
|
|
|
|
/// Make a Symbol but don't add it to the scope.
|
|
template<typename D>
|
|
Symbol &MakeSymbol(const SourceName &name, Attrs attrs, D &&details) {
|
|
return allSymbols.Make(*this, name, attrs, std::move(details));
|
|
}
|
|
|
|
std::list<Scope> &children() { return children_; }
|
|
const std::list<Scope> &children() const { return children_; }
|
|
|
|
// For Module scope, maintain a mapping of all submodule scopes with this
|
|
// module as its ancestor module. AddSubmodule returns false if already there.
|
|
Scope *FindSubmodule(const SourceName &) const;
|
|
bool AddSubmodule(const SourceName &, Scope &);
|
|
|
|
DerivedTypeSpec &MakeDerivedTypeSpec(const SourceName &);
|
|
|
|
// For modules read from module files, this is the stream of characters
|
|
// that are referenced by SourceName objects.
|
|
void set_chars(std::string &&chars) { chars_ = std::move(chars); }
|
|
|
|
ImportKind GetImportKind() const;
|
|
// Names appearing in IMPORT statements in this scope
|
|
std::set<SourceName> importNames() const { return importNames_; }
|
|
|
|
// Set the kind of imports from host into this scope.
|
|
// Return an error message for incompatible kinds.
|
|
std::optional<parser::MessageFixedText> SetImportKind(ImportKind);
|
|
|
|
bool add_importName(const SourceName &);
|
|
|
|
private:
|
|
Scope &parent_;
|
|
const Kind kind_;
|
|
Symbol *const symbol_;
|
|
std::list<Scope> children_;
|
|
mapType symbols_;
|
|
std::map<SourceName, Scope *> submodules_;
|
|
std::list<DerivedTypeSpec> derivedTypeSpecs_;
|
|
std::string chars_;
|
|
std::optional<ImportKind> importKind_;
|
|
std::set<SourceName> importNames_;
|
|
|
|
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
|
|
// or Symbol& points to one in there.
|
|
static Symbols<1024> allSymbols;
|
|
|
|
bool CanImport(const SourceName &) const;
|
|
|
|
friend std::ostream &operator<<(std::ostream &, const Scope &);
|
|
};
|
|
|
|
} // namespace Fortran::semantics
|
|
#endif // FORTRAN_SEMANTICS_SCOPE_H_
|