a3de9d789c
A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04d Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
50 lines
1.3 KiB
C++
50 lines
1.3 KiB
C++
#include "scope.h"
|
|
#include "symbol.h"
|
|
#include <memory>
|
|
|
|
namespace Fortran {
|
|
namespace semantics {
|
|
|
|
const Scope Scope::systemScope{Scope::systemScope, Scope::Kind::System};
|
|
Scope Scope::globalScope{Scope::systemScope, Scope::Kind::Global};
|
|
|
|
Scope &Scope::MakeScope(Kind kind) {
|
|
children_.emplace_back(*this, kind);
|
|
return children_.back();
|
|
}
|
|
|
|
Symbol &Scope::GetOrMakeSymbol(const Name &name) {
|
|
const auto it = symbols_.find(name);
|
|
if (it != symbols_.end()) {
|
|
return it->second;
|
|
} else {
|
|
return MakeSymbol(name);
|
|
}
|
|
}
|
|
|
|
Symbol &Scope::MakeSymbol(const Name &name, const Attrs &attrs) {
|
|
return MakeSymbol(name, attrs, UnknownDetails());
|
|
}
|
|
|
|
static const char *ToString(Scope::Kind kind) {
|
|
switch (kind) {
|
|
case Scope::Kind::System: return "System";
|
|
case Scope::Kind::Global: return "Global";
|
|
case Scope::Kind::Module: return "Module";
|
|
case Scope::Kind::MainProgram: return "MainProgram";
|
|
case Scope::Kind::Subprogram: return "Subprogram";
|
|
default: CRASH_NO_CASE;
|
|
}
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &os, const Scope &scope) {
|
|
os << ToString(scope.kind()) << " scope: " << scope.children_.size()
|
|
<< " children\n";
|
|
for (const auto &sym : scope.symbols_) {
|
|
os << " " << sym.second << "\n";
|
|
}
|
|
return os;
|
|
}
|
|
|
|
} // namespace semantics
|
|
} // namespace Fortran
|