Each Scope now tracks the source locations that it and its nested scopes
span. This is achieved by extending the source range of a scope for each
statement encountered while it is the current scope.
Semantics::FindScope maps a source location (from the cooked character
stream) to the narrowest scope that contains it.
Original-commit: flang-compiler/f18@
7b4d2bb113e4a1018c5f6aa740b02e423ff61799
Reviewed-on: https://github.com/flang-compiler/f18/pull/230
Tree-same-pre-rewrite: false
return interval_.start()[j];
}
+ bool Contains(const CharBlock &that) const {
+ return interval_.Contains(that.interval_);
+ }
+
bool IsBlank() const {
for (char ch : *this) {
if (ch != ' ' && ch != '\t') {
void set_messages(parser::Messages &messages) { messages_ = &messages; }
- template<typename T> bool Pre(const parser::Statement<T> &x) {
- currStmtSource_ = &x.source;
- return true;
- }
- template<typename T> void Post(const parser::Statement<T> &) {
- currStmtSource_ = nullptr;
- }
-
const SourceName *currStmtSource() { return currStmtSource_; }
+ void set_currStmtSource(const SourceName *x) { currStmtSource_ = x; }
// Add a message to the messages to be emitted.
Message &Say(Message &&);
public:
using DeclTypeSpecVisitor::Post;
using DeclTypeSpecVisitor::Pre;
- using MessageHandler::Post;
- using MessageHandler::Pre;
using ImplicitNoneNameSpec = parser::ImplicitStmt::ImplicitNoneNameSpec;
void Post(const parser::ParameterStmt &);
ImplicitRulesVisitor::ClearScopes();
}
+ template<typename T> bool Pre(const parser::Statement<T> &x) {
+ set_currStmtSource(&x.source);
+ currScope_->AddSourceRange(x.source);
+ return true;
+ }
+ template<typename T> void Post(const parser::Statement<T> &) {
+ set_currStmtSource(nullptr);
+ }
+
Symbol *FindSymbol(const SourceName &name);
void EraseSymbol(const SourceName &name);
using InterfaceVisitor::Pre;
using ModuleVisitor::Post;
using ModuleVisitor::Pre;
+ using ScopeHandler::Post;
+ using ScopeHandler::Pre;
using SubprogramVisitor::Post;
using SubprogramVisitor::Pre;
}
}
+const Scope *Scope::FindScope(const parser::CharBlock &source) const {
+ if (!sourceRange_.Contains(source)) {
+ return nullptr;
+ }
+ for (const auto &child : children_) {
+ if (const auto *scope{child.FindScope(source)}) {
+ return scope;
+ }
+ }
+ return this;
+}
+
+void Scope::AddSourceRange(const parser::CharBlock &source) {
+ if (sourceRange_.empty()) {
+ sourceRange_ = source;
+ } else if (!source.empty()) {
+ sourceRange_ =
+ parser::CharBlock(std::min(sourceRange_.begin(), source.begin()),
+ std::max(sourceRange_.end(), source.end()));
+ }
+}
+
std::ostream &operator<<(std::ostream &os, const Scope &scope) {
os << Scope::EnumToString(scope.kind()) << " scope: ";
if (auto *symbol{scope.symbol()}) {
bool add_importName(const SourceName &);
+ // The range of the source of this and nested scopes.
+ const parser::CharBlock &sourceRange() const { return sourceRange_; }
+ void AddSourceRange(const parser::CharBlock &);
+ // Find the smallest scope under this one that contains source
+ const Scope *FindScope(const parser::CharBlock &) const;
+
private:
Scope &parent_;
const Kind kind_;
+ parser::CharBlock sourceRange_;
Symbol *const symbol_;
std::list<Scope> children_;
mapType symbols_;
return !AnyFatalError();
}
+const Scope &Semantics::FindScope(const parser::CharBlock &source) const {
+ if (const auto *scope{context_.globalScope().FindScope(source)}) {
+ return *scope;
+ } else {
+ common::die("invalid source location");
+ }
+}
+
void Semantics::EmitMessages(std::ostream &os) const {
context_.messages().Emit(os, cooked_);
}
public:
explicit Semantics(SemanticsContext &context, parser::Program &program,
parser::CookedSource &cooked)
- : context_{context}, program_{program}, cooked_{cooked} {}
+ : context_{context}, program_{program}, cooked_{cooked} {
+ context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()});
+ }
SemanticsContext &context() const { return context_; }
bool Perform();
+ const Scope &FindScope(const parser::CharBlock &) const;
bool AnyFatalError() const { return context_.AnyFatalError(); }
void EmitMessages(std::ostream &) const;
void DumpSymbols(std::ostream &);