llvm/flang/lib/semantics/scope.h
Tim Keith 1c291436f5 [flang] Implement parse tree rewriting.
Add parse-tree-mutator.h like parse-tree-visitor.h except that the Walk
functions take non-const references to parse tree nodes so the Pre and
Post methods of the mutator that are passed around can make changes to
the parse tree.

Change ExecutionPart to be a class that wraps a list so that it can be
identified during parse tree walking.

Add Symbol* field to parser::Name for the result of symbol resolution.
In parse tree dumper, dump symbol when it is there instead of just name.

Add RewriteParseTree to walk the parse tree, fill in resolved symbols in
Name nodes, and make necessary changes to the structure. Currently that
consists of rewriting statement functions as array assignments when
appropriate.

In ResolveNames, call RewriteParseTree if the resolution was successful.
Recognize a statement function that comes after a mis-identified
statement function and report an error. resolve08.f90 tests this case.

Add -fdebug-dump-symbols to dump the scope tree and symbols in each scope.
This is implemented by DumpSymbols in resolve-names.cc. Add an optional
symbol to scopes that correspond to symbols (e.g. subprograms). Remove
debug output from ResolveNamesVisitor as this option can be used instead.

Original-commit: flang-compiler/f18@9cd3372265
Reviewed-on: https://github.com/flang-compiler/f18/pull/60
Tree-same-pre-rewrite: false
2018-04-18 15:06:35 -07:00

86 lines
2.6 KiB
C++

#ifndef FORTRAN_SEMANTICS_SCOPE_H_
#define FORTRAN_SEMANTICS_SCOPE_H_
#include "attr.h"
#include "symbol.h"
#include "../parser/idioms.h"
#include "../parser/parse-tree.h"
#include <list>
#include <map>
#include <string>
namespace Fortran::semantics {
class Scope {
using mapType = std::map<SourceName, Symbol>;
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, const Symbol *symbol)
: parent_{parent}, kind_{kind}, symbol_{symbol} {}
const Scope &parent() const {
CHECK(kind_ != Kind::System);
return parent_;
}
Kind kind() const { return kind_; }
const Symbol *symbol() const { return symbol_; }
/// Make a scope nested in this one
Scope &MakeScope(Kind kind, const 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) { return symbols_.find(name); }
const_iterator find(const SourceName &name) const {
return symbols_.find(name);
}
size_type erase(const SourceName &name) { return symbols_.erase(name); }
/// 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) {
return symbols_.try_emplace(name, *this, name, attrs, details);
}
std::list<Scope> &children() { return children_; }
const std::list<Scope> &children() const { return children_; }
private:
const Scope &parent_;
const Kind kind_;
const Symbol *const symbol_;
std::list<Scope> children_;
mapType symbols_;
friend std::ostream &operator<<(std::ostream &, const Scope &);
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SCOPE_H_