2541df532a
This consists of: - a new kind of symbols to represent them with DerivedTypeDetails - creating symbols for derived types when they are declared - creating a new kind of scope for the type to hold component symbols - resolving entity declarations of objects of derived type - resolving references to objects of derived type and to components - handling derived types with same name as generic Type parameters are not yet implemented. Refactor DeclTypeSpec to be a value class wrapping an IntrinsicTypeSpec or a DerivedTypeSpec (or neither in the TypeStar and ClassStar cases). Store DerivedTypeSpec objects in a new structure the current scope MakeDerivedTypeSpec so that DeclTypeSpec can just contain a pointer to them, as it currently does for intrinsic types. In GenericDetails, add derivedType field to handle case where generic and derived type have the same name. The generic is in the scope and the derived type is referenced from the generic, similar to the case where a generic and specific have the same name. When one of these names is mis-recognized, we sometimes have to fix up the 'occurrences' lists of the symbols. Assign implicit types as soon as an entity is encountered that requires one. Otherwise implicit derived types won't work. When we see 'x%y' we have to know the type of x in order to resolve y. Add an Implicit flag to mark symbols that were implicitly typed For symbols that introduce a new scope, include a pointer back to that scope. Add CurrNonTypeScope() for the times when we want the current scope but ignoring derived type scopes. For example, that happens when looking for types or parameters, or creating implicit symbols. Original-commit: flang-compiler/f18@9bd16da020 Reviewed-on: https://github.com/flang-compiler/f18/pull/109
125 lines
3.9 KiB
C++
125 lines
3.9 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/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 Scope systemScope;
|
|
static Scope globalScope; // contains program-units
|
|
|
|
ENUM_CLASS(Kind, System, Global, Module, MainProgram, Subprogram, DerivedType)
|
|
|
|
Scope(Scope &parent, Kind kind, Symbol *symbol)
|
|
: parent_{parent}, kind_{kind}, symbol_{symbol} {
|
|
if (symbol) {
|
|
symbol->set_scope(this);
|
|
}
|
|
}
|
|
|
|
Scope &parent() {
|
|
CHECK(kind_ != Kind::System);
|
|
return parent_;
|
|
}
|
|
const Scope &parent() const {
|
|
CHECK(kind_ != Kind::System);
|
|
return parent_;
|
|
}
|
|
Kind kind() const { return kind_; }
|
|
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 &);
|
|
|
|
/// 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_.insert(std::make_pair(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_; }
|
|
|
|
DerivedTypeSpec &MakeDerivedTypeSpec(const SourceName &);
|
|
|
|
private:
|
|
Scope &parent_;
|
|
const Kind kind_;
|
|
Symbol *const symbol_;
|
|
std::list<Scope> children_;
|
|
mapType symbols_;
|
|
std::list<DerivedTypeSpec> derivedTypeSpecs_;
|
|
|
|
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
|
|
// or Symbol& points to one in there.
|
|
static Symbols<1024> allSymbols;
|
|
|
|
friend std::ostream &operator<<(std::ostream &, const Scope &);
|
|
};
|
|
|
|
} // namespace Fortran::semantics
|
|
#endif // FORTRAN_SEMANTICS_SCOPE_H_
|