[flang] several changes following pull comments
Original-commit: flang-compiler/f18@ba1275a7cb Reviewed-on: https://github.com/flang-compiler/f18/pull/24 Tree-same-pre-rewrite: false
This commit is contained in:
parent
b65824fb32
commit
99dd6d03de
|
@ -7,6 +7,89 @@
|
|||
namespace Fortran {
|
||||
namespace semantics {
|
||||
|
||||
|
||||
// A class describing an identifier.
|
||||
//
|
||||
// All Identifiers associated to the same name are sharing the same
|
||||
// storage for that name. That makes comparison of 'Identifier'
|
||||
// very fast since the strings do not have to be compared.
|
||||
//
|
||||
|
||||
class Identifier;
|
||||
|
||||
typedef std::optional<Identifier> OptIdentifier ;
|
||||
|
||||
class Identifier
|
||||
{
|
||||
private:
|
||||
const std::string *text_ ;
|
||||
public:
|
||||
Identifier() = delete ;
|
||||
|
||||
Identifier(const Identifier &in) : text_(in.text_) {}
|
||||
|
||||
Identifier(const std::string &);
|
||||
|
||||
// Construct an Identifier from a constant C-string.
|
||||
//
|
||||
// That constructor is not entirely redundant with the std::string
|
||||
// constructor because it serves a secundary purpose: catch the illegal
|
||||
// use of 0 to initialize an Identifier.
|
||||
//
|
||||
// Without it, the std::string constructor would be called (since 0
|
||||
// is somehow a legal std::string initializer). The result would be an
|
||||
// 'std::logic_error' exception.
|
||||
//
|
||||
Identifier(const char *);
|
||||
|
||||
|
||||
// Helper to create
|
||||
static Identifier make(const std::string &text) { return Identifier(text); }
|
||||
|
||||
// Helper to create OptIdentifier
|
||||
static std::optional<Identifier> make(const std::optional<std::string> &text) {
|
||||
if (text) {
|
||||
return Identifier(*text);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const Identifier &a) const {
|
||||
return text_ == a.text_ ;
|
||||
}
|
||||
|
||||
bool operator!=(const Identifier &a) const {
|
||||
return text_ != a.text_ ;
|
||||
}
|
||||
|
||||
bool operator<(const Identifier &a) const {
|
||||
return name() < a.name() ;
|
||||
}
|
||||
|
||||
bool operator<=(const Identifier &a) const {
|
||||
return name() <= a.name() ;
|
||||
}
|
||||
|
||||
bool operator>(const Identifier &a) const {
|
||||
return name() > a.name() ;
|
||||
}
|
||||
|
||||
bool operator>=(const Identifier &a) const {
|
||||
return name() >= a.name() ;
|
||||
}
|
||||
|
||||
const std::string & name() const {
|
||||
return *text_ ;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// A class describing an identifier.
|
||||
//
|
||||
// For each name, there is one and only one identifier.
|
||||
|
@ -34,6 +117,7 @@ public:
|
|||
return n ? Identifier::get(n.value()) : nullptr ;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace semantics
|
||||
} // namespace Fortran
|
||||
|
|
|
@ -30,7 +30,7 @@ class Scope;
|
|||
//
|
||||
class Scope {
|
||||
public:
|
||||
enum Kind {
|
||||
enum class Kind {
|
||||
SK_SYSTEM, // the unique scope associated to the system (and providing
|
||||
// intrinsic procedures)
|
||||
SK_GLOBAL, // the unique global scope containing all units
|
||||
|
@ -56,7 +56,7 @@ private:
|
|||
Kind kind_;
|
||||
|
||||
//
|
||||
// For most ranks, id contains a unique identifier that is increased
|
||||
// For most ranks, id contains a district identifier that is increased
|
||||
// each time a new Scope is created.
|
||||
//
|
||||
// The System and Global scope respectively have 0 and 1
|
||||
|
@ -100,7 +100,7 @@ private:
|
|||
Scope *module;
|
||||
// All identifiers to exclude when doing a lookup
|
||||
// in that module
|
||||
std::vector<Identifier *> exclude;
|
||||
std::vector<Identifier> exclude;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -111,11 +111,8 @@ private:
|
|||
|
||||
Scope *parent_scope_;
|
||||
|
||||
// The host scope is the scope that is searched last. 9
|
||||
//
|
||||
//
|
||||
//
|
||||
Scope *host_scope_; // The host scope
|
||||
// The host scope is the scope that is searched last.
|
||||
Scope *host_scope_;
|
||||
|
||||
std::list<Scope *> use_; // Scopes for the modules that are entirely used
|
||||
std::list<Scope *>
|
||||
|
@ -174,7 +171,7 @@ private:
|
|||
std::vector<Symbol *> owned_;
|
||||
|
||||
public:
|
||||
Kind getKind() const { return kind_; }
|
||||
Kind kind() const { return kind_; }
|
||||
|
||||
const Scope *getParentScope() const { return parent_scope_; }
|
||||
Scope *getParentScope() { return parent_scope_; }
|
||||
|
@ -187,8 +184,8 @@ public:
|
|||
//
|
||||
// The Global scope is the scope that is immediately below the System scope.
|
||||
//
|
||||
// It contains the symbols for the Program unit (PROGRAM, MODULE, FUNCTION,
|
||||
// SUBROUTINE and BLOCKDATA)
|
||||
// It contains the symbols for the Program unit (PROGRAM, MODULE, SUBMODULE,
|
||||
// FUNCTION, SUBROUTINE and BLOCKDATA)
|
||||
//
|
||||
// However, that scope is not standard in the sense that it requires a
|
||||
// dedicated lookup to find its symbols.
|
||||
|
@ -201,32 +198,32 @@ public:
|
|||
const Scope *getGlobalScope() const;
|
||||
|
||||
// Look for a symbol locally and in the host scope (if any)
|
||||
Symbol *Lookup(const Identifier *name);
|
||||
const Symbol *Lookup(const Identifier *name) const;
|
||||
Symbol *Lookup(Identifier name);
|
||||
const Symbol *Lookup(Identifier name) const;
|
||||
|
||||
// Look for a symbol locally (do not explore the host scope).
|
||||
//
|
||||
Symbol *LookupLocal(const Identifier *name);
|
||||
const Symbol *LookupLocal(const Identifier *name) const;
|
||||
Symbol *LookupLocal(Identifier name);
|
||||
const Symbol *LookupLocal(Identifier name) const;
|
||||
|
||||
//
|
||||
// Lookup for a Program Unit by name
|
||||
//
|
||||
Symbol *LookupProgramUnit(const Identifier *name);
|
||||
const Symbol *LookupProgramUnit(const Identifier *name) const;
|
||||
Symbol *LookupProgramUnit(Identifier name);
|
||||
const Symbol *LookupProgramUnit(Identifier name) const;
|
||||
|
||||
//
|
||||
// Lookup for a known module.
|
||||
//
|
||||
// The result is either null or a scope of kind SK_USE_MODULE.
|
||||
//
|
||||
Symbol *LookupModule(const Identifier *name);
|
||||
const Symbol *LookupModule(const Identifier *name) const;
|
||||
Symbol *LookupModule(Identifier name);
|
||||
const Symbol *LookupModule(Identifier name) const;
|
||||
|
||||
//
|
||||
// Provide the distinct id associated to each scope
|
||||
//
|
||||
//
|
||||
int getId() const;
|
||||
int id() const;
|
||||
|
||||
//
|
||||
// Add a symbol to the scope.
|
||||
|
@ -243,4 +240,4 @@ public:
|
|||
|
||||
} // namespace Fortran::semantics
|
||||
|
||||
#endif
|
||||
#endif // FLANG_SEMA_SCOPE_H
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Fortran::semantics {
|
|||
|
||||
//
|
||||
// A StatementMap describes the relations between statements in a program unit
|
||||
// and also hold information that are common each statement (label, provenance,
|
||||
// and also hold information that are common to each statement (label, provenance,
|
||||
// ...)
|
||||
//
|
||||
// In the parse-tree each struct representing a statement (see Stmt.def)
|
||||
|
@ -34,7 +34,7 @@ namespace Fortran::semantics {
|
|||
// the 'parent' of each statement in that body.
|
||||
//
|
||||
// The mapping of Fortran statements to the 4 groups Single, Start,
|
||||
// Part, and End shall be obvious.
|
||||
// Part, and End should be obvious.
|
||||
//
|
||||
// For instance, consider the following piece of code
|
||||
//
|
||||
|
@ -69,12 +69,12 @@ namespace Fortran::semantics {
|
|||
// The '>', '+' and '>' are used to mark the Start, Part and End statements.
|
||||
//
|
||||
// In that dump, we see that:
|
||||
// - The DO construct is composed of statements 10 and 21
|
||||
// - The IF construct is composed of statements 12, 15, 17 and 19
|
||||
// - The body of statement 10 is composed of statements 11, 12, and 20
|
||||
// - The body of statement 12 is composed of statements 13 and 14
|
||||
// - The body of statement 15 is composed of statement 16
|
||||
// - The body of statement 17 is composed of statement 18
|
||||
// - The DO construct is comprised of statements 10 and 21
|
||||
// - The IF construct is comprised of statements 12, 15, 17 and 19
|
||||
// - The body of statement 10 is comprised of statements 11, 12, and 20
|
||||
// - The body of statement 12 is comprised of statements 13 and 14
|
||||
// - The body of statement 15 is comprised of statement 16
|
||||
// - The body of statement 17 is comprised of statement 18
|
||||
//
|
||||
// For the few Fortran constructs that do not provide an explicit 'End'
|
||||
// statement, a dummy entry will be provided in the map. For instance,
|
||||
|
@ -93,7 +93,7 @@ class StatementMap {
|
|||
public:
|
||||
typedef int Index; // should become an opaque type.
|
||||
|
||||
static const Index None = 0;
|
||||
static constexpr Index None = 0;
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
|
@ -155,7 +155,6 @@ public:
|
|||
|
||||
StmtGroup GetGroup(Index index) const { return Get(index).group; }
|
||||
|
||||
|
||||
// Provide the numerical label associated to that statement or 0.
|
||||
// Be aware that labels are not necessarily unique and so cannot
|
||||
// be used to identify a statement within the whole map.
|
||||
|
@ -185,7 +184,7 @@ public:
|
|||
Index FirstInBody(Index index) const;
|
||||
Index LastInBody(Index index) const;
|
||||
|
||||
// Functionnally equivalent to LastInBody(PreviousPartOfConstruct(index))
|
||||
// Functionally equivalent to LastInBody(PreviousPartOfConstruct(index))
|
||||
Index LastInPreviousBody(Index index) const;
|
||||
Index FindPrevInConstruct(Index index, StmtClass sclass) const;
|
||||
|
||||
|
@ -214,13 +213,13 @@ public:
|
|||
// Visit all the statements that compose a construct.
|
||||
//
|
||||
// 'stmt' shall be a construct component (so in group Start, Part or End)
|
||||
void VisistConstruct(Index stmt, std::function<bool(Index)> action) const;
|
||||
void VisitConstruct(Index stmt, std::function<bool(Index)> action) const;
|
||||
|
||||
// Visit all the statements that compose a construct in reverse order.
|
||||
//
|
||||
// 'stmt' shall be a construct component (so in group Start, Part or End)
|
||||
//
|
||||
void VisistConstructRev(Index stmt, std::function<bool(Index)> action) const;
|
||||
void VisitConstructRev(Index stmt, std::function<bool(Index)> action) const;
|
||||
};
|
||||
|
||||
} // namespace Fortran::semantics
|
||||
|
|
|
@ -29,11 +29,11 @@ public:
|
|||
private:
|
||||
ClassId cid_;
|
||||
Scope *owner_; // The scope that owns this symbol
|
||||
const Identifier *name_; // The local name of that symbol
|
||||
Identifier ident_; // The local name of that symbol
|
||||
private:
|
||||
TypeSpec *type_ = nullptr; // The type associated to that symbol
|
||||
public:
|
||||
Symbol(ClassId cid, Scope *owner, const Identifier *name);
|
||||
Symbol(ClassId cid, Scope *owner, Identifier name);
|
||||
|
||||
public:
|
||||
// For now, provide some toXXXX() member to perform the dynamic cast.
|
||||
|
@ -53,11 +53,11 @@ public:
|
|||
public:
|
||||
Scope *owner() { return owner_; }
|
||||
|
||||
const Identifier *name() { return name_; }
|
||||
Identifier name() { return ident_; }
|
||||
|
||||
bool Match(const Identifier *ident) { return ident == name_; }
|
||||
bool Match(Identifier ident) { return ident == ident_; }
|
||||
|
||||
std::string toString() const { return name_->name(); }
|
||||
std::string toString() const { return ident_.name(); }
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
//
|
||||
class TemporarySymbol : public Symbol {
|
||||
public:
|
||||
TemporarySymbol(Scope *owner, const Identifier *name)
|
||||
TemporarySymbol(Scope *owner, Identifier name)
|
||||
: Symbol(TemporarySymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -90,7 +90,7 @@ private:
|
|||
//
|
||||
class ModuleSymbol : public Symbol {
|
||||
public:
|
||||
ModuleSymbol(Scope *owner, const Identifier *name)
|
||||
ModuleSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ProgramSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -101,7 +101,7 @@ private:
|
|||
//
|
||||
class ProgramSymbol : public Symbol {
|
||||
public:
|
||||
ProgramSymbol(Scope *owner, const Identifier *name)
|
||||
ProgramSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ProgramSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -112,7 +112,7 @@ private:
|
|||
//
|
||||
class BlockDataSymbol : public Symbol {
|
||||
public:
|
||||
BlockDataSymbol(Scope *owner, const Identifier *name)
|
||||
BlockDataSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(BlockDataSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -123,14 +123,14 @@ private:
|
|||
//
|
||||
class ParameterSymbol : public Symbol {
|
||||
public:
|
||||
ParameterSymbol(Scope *owner, const Identifier *name)
|
||||
ParameterSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ParameterSymbolId, owner, name) {}
|
||||
};
|
||||
|
||||
// A symbol representing an EXTERNAL function.
|
||||
class ExternalSymbol : public Symbol {
|
||||
public:
|
||||
ExternalSymbol(Scope *owner, const Identifier *name)
|
||||
ExternalSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ExternalSymbolId, owner, name) {}
|
||||
};
|
||||
|
||||
|
@ -144,14 +144,14 @@ public:
|
|||
//
|
||||
class VariableSymbol : public Symbol {
|
||||
public:
|
||||
VariableSymbol(Scope *owner, const Identifier *name)
|
||||
VariableSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(VariableSymbolId, owner, name) {}
|
||||
};
|
||||
|
||||
// A symbol representing a dummy argument.
|
||||
class DummyArgumentSymbol : public Symbol {
|
||||
public:
|
||||
DummyArgumentSymbol(Scope *owner, const Identifier *name)
|
||||
DummyArgumentSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(DummyArgumentSymbolId, owner, name) {}
|
||||
};
|
||||
|
||||
|
@ -164,12 +164,12 @@ public:
|
|||
//
|
||||
class CommonSymbol : public Symbol {
|
||||
public:
|
||||
CommonSymbol(Scope *owner, const Identifier *name)
|
||||
CommonSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(CommonSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
// The content of the common section.
|
||||
std::vector<const Identifier *> content_;
|
||||
std::vector<Identifier > content_;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -181,7 +181,7 @@ private:
|
|||
//
|
||||
class SubroutineSymbol : public Symbol {
|
||||
public:
|
||||
SubroutineSymbol(Scope *owner, const Identifier *name)
|
||||
SubroutineSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(SubroutineSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -191,7 +191,7 @@ private:
|
|||
|
||||
class FunctionSymbol : public Symbol {
|
||||
public:
|
||||
FunctionSymbol(Scope *owner, const Identifier *name)
|
||||
FunctionSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(FunctionSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -204,7 +204,7 @@ private:
|
|||
// A null name is allowed to represent an unnamed interface.
|
||||
class InterfaceSymbol : public Symbol {
|
||||
public:
|
||||
InterfaceSymbol(Scope *owner, const Identifier *name)
|
||||
InterfaceSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(InterfaceSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -215,7 +215,7 @@ private:
|
|||
// automatically or via an 'import' statement.
|
||||
class ImportedSymbol : public Symbol {
|
||||
public:
|
||||
ImportedSymbol(Scope *owner, const Identifier *name)
|
||||
ImportedSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ImportedSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -240,7 +240,7 @@ private:
|
|||
//
|
||||
class SubSymbol : public Symbol {
|
||||
public:
|
||||
SubSymbol(Scope *owner, const Identifier *name)
|
||||
SubSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(SubSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -258,7 +258,7 @@ private:
|
|||
//
|
||||
class UsedSymbol : public Symbol {
|
||||
public:
|
||||
UsedSymbol(Scope *owner, const Identifier *name)
|
||||
UsedSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(UsedSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -272,7 +272,7 @@ private:
|
|||
//
|
||||
class DerivedTypeSymbol : public Symbol {
|
||||
public:
|
||||
DerivedTypeSymbol(Scope *owner, const Identifier *name)
|
||||
DerivedTypeSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(DerivedTypeSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -284,7 +284,7 @@ private:
|
|||
//
|
||||
class MemberSymbol : public Symbol {
|
||||
public:
|
||||
MemberSymbol(Scope *owner, const Identifier *name)
|
||||
MemberSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(MemberSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -295,7 +295,7 @@ private:
|
|||
//
|
||||
class NamelistSymbol : public Symbol {
|
||||
public:
|
||||
NamelistSymbol(Scope *owner, const Identifier *name)
|
||||
NamelistSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(NamelistSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
@ -307,7 +307,7 @@ private:
|
|||
//
|
||||
class ConstructSymbol : public Symbol {
|
||||
public:
|
||||
ConstructSymbol(Scope *owner, const Identifier *name)
|
||||
ConstructSymbol(Scope *owner, Identifier name)
|
||||
: Symbol(ConstructSymbolId, owner, name) {}
|
||||
|
||||
private:
|
||||
|
|
|
@ -4,6 +4,7 @@ add_library( FlangSemantics
|
|||
Scope.cc
|
||||
Symbol.cc
|
||||
StatementMap.cc
|
||||
ParseTreeDump.cc
|
||||
Type.cc # ../semantics/type.cc
|
||||
Attr.cc # ../semantics/attr.cc
|
||||
)
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
|
||||
#include "flang/Sema/Identifier.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
using Fortran::semantics::Identifier;
|
||||
|
||||
static std::map<std::string, Identifier *> all;
|
||||
static std::set<std::string> all;
|
||||
|
||||
const Identifier *Identifier::get(std::string n) {
|
||||
Identifier *&ref = all[n];
|
||||
if (!ref) {
|
||||
ref = new Identifier(n);
|
||||
}
|
||||
return ref;
|
||||
Identifier::Identifier(const std::string &text)
|
||||
{
|
||||
// TODO: Produce a proper 'ICE' if empty text.
|
||||
assert( text.size() > 0 ) ;
|
||||
text_ = &(*(all.insert(text).first)) ;
|
||||
}
|
||||
|
||||
Identifier::Identifier(const char *text)
|
||||
{
|
||||
// TODO: Produce a proper 'ICE' if text is empty or null.
|
||||
assert(text) ;
|
||||
assert(text[0] != '\0' ); // cheaper than strlen(text)==0
|
||||
text_ = &(*(all.insert( std::string(text) ).first)) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,97 +11,97 @@ Scope::Scope(Kind k, Scope *p, Symbol *s)
|
|||
: kind_(k), id_or_counter_(0), self_(s), parent_scope_(p), host_scope_(p) {
|
||||
switch (k) {
|
||||
|
||||
case SK_SYSTEM:
|
||||
case Kind::SK_SYSTEM:
|
||||
assert(parent_scope_ == NULL);
|
||||
id_or_counter_ = -1;
|
||||
break;
|
||||
|
||||
case SK_GLOBAL:
|
||||
assert(parent_scope_->kind_ == SK_SYSTEM);
|
||||
case Kind::SK_GLOBAL:
|
||||
assert(parent_scope_->kind_ == Kind::SK_SYSTEM);
|
||||
id_or_counter_ = 2;
|
||||
break;
|
||||
|
||||
case SK_PROGRAM:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL);
|
||||
case Kind::SK_PROGRAM:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL);
|
||||
if (self_) {
|
||||
assert(self_->owner() == parent_scope_);
|
||||
}
|
||||
break;
|
||||
|
||||
case SK_MODULE:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL);
|
||||
case Kind::SK_MODULE:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_SUBMODULE:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL);
|
||||
case Kind::SK_SUBMODULE:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_FUNCTION:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL ||
|
||||
parent_scope_->kind_ == SK_PROGRAM ||
|
||||
parent_scope_->kind_ == SK_MODULE ||
|
||||
parent_scope_->kind_ == SK_FUNCTION ||
|
||||
parent_scope_->kind_ == SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == SK_INTERFACE ||
|
||||
parent_scope_->kind_ == SK_USE_MODULE);
|
||||
case Kind::SK_FUNCTION:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL ||
|
||||
parent_scope_->kind_ == Kind::SK_PROGRAM ||
|
||||
parent_scope_->kind_ == Kind::SK_MODULE ||
|
||||
parent_scope_->kind_ == Kind::SK_FUNCTION ||
|
||||
parent_scope_->kind_ == Kind::SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == Kind::SK_INTERFACE ||
|
||||
parent_scope_->kind_ == Kind::SK_USE_MODULE);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_SUBROUTINE:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL ||
|
||||
parent_scope_->kind_ == SK_PROGRAM ||
|
||||
parent_scope_->kind_ == SK_MODULE ||
|
||||
parent_scope_->kind_ == SK_FUNCTION ||
|
||||
parent_scope_->kind_ == SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == SK_INTERFACE ||
|
||||
parent_scope_->kind_ == SK_USE_MODULE);
|
||||
case Kind::SK_SUBROUTINE:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL ||
|
||||
parent_scope_->kind_ == Kind::SK_PROGRAM ||
|
||||
parent_scope_->kind_ == Kind::SK_MODULE ||
|
||||
parent_scope_->kind_ == Kind::SK_FUNCTION ||
|
||||
parent_scope_->kind_ == Kind::SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == Kind::SK_INTERFACE ||
|
||||
parent_scope_->kind_ == Kind::SK_USE_MODULE);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_BLOCKDATA:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL);
|
||||
case Kind::SK_BLOCKDATA:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_USE_MODULE:
|
||||
assert(parent_scope_->kind_ == SK_GLOBAL);
|
||||
case Kind::SK_USE_MODULE:
|
||||
assert(parent_scope_->kind_ == Kind::SK_GLOBAL);
|
||||
assert(self_);
|
||||
assert(self_->owner() == parent_scope_);
|
||||
break;
|
||||
|
||||
case SK_BLOCK:
|
||||
assert(parent_scope_->kind_ == SK_PROGRAM ||
|
||||
parent_scope_->kind_ == SK_BLOCK ||
|
||||
parent_scope_->kind_ == SK_FUNCTION ||
|
||||
parent_scope_->kind_ == SK_SUBROUTINE);
|
||||
case Kind::SK_BLOCK:
|
||||
assert(parent_scope_->kind_ == Kind::SK_PROGRAM ||
|
||||
parent_scope_->kind_ == Kind::SK_BLOCK ||
|
||||
parent_scope_->kind_ == Kind::SK_FUNCTION ||
|
||||
parent_scope_->kind_ == Kind::SK_SUBROUTINE);
|
||||
if (self_) {
|
||||
assert(self_->owner() == parent_scope_);
|
||||
assert(self_->toConstructSymbol());
|
||||
}
|
||||
break;
|
||||
|
||||
case SK_DERIVED:
|
||||
assert(parent_scope_->kind_ == SK_PROGRAM ||
|
||||
parent_scope_->kind_ == SK_MODULE ||
|
||||
parent_scope_->kind_ == SK_FUNCTION ||
|
||||
parent_scope_->kind_ == SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == SK_INTERFACE ||
|
||||
parent_scope_->kind_ == SK_USE_MODULE);
|
||||
case Kind::SK_DERIVED:
|
||||
assert(parent_scope_->kind_ == Kind::SK_PROGRAM ||
|
||||
parent_scope_->kind_ == Kind::SK_MODULE ||
|
||||
parent_scope_->kind_ == Kind::SK_FUNCTION ||
|
||||
parent_scope_->kind_ == Kind::SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == Kind::SK_INTERFACE ||
|
||||
parent_scope_->kind_ == Kind::SK_USE_MODULE);
|
||||
break;
|
||||
|
||||
case SK_INTERFACE:
|
||||
assert(parent_scope_->kind_ == SK_PROGRAM ||
|
||||
parent_scope_->kind_ == SK_MODULE ||
|
||||
parent_scope_->kind_ == SK_FUNCTION ||
|
||||
parent_scope_->kind_ == SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == SK_USE_MODULE);
|
||||
case Kind::SK_INTERFACE:
|
||||
assert(parent_scope_->kind_ == Kind::SK_PROGRAM ||
|
||||
parent_scope_->kind_ == Kind::SK_MODULE ||
|
||||
parent_scope_->kind_ == Kind::SK_FUNCTION ||
|
||||
parent_scope_->kind_ == Kind::SK_SUBROUTINE ||
|
||||
parent_scope_->kind_ == Kind::SK_USE_MODULE);
|
||||
|
||||
// Within an interface, the symbols must be explicitly imported
|
||||
// from the parent scope so there is no default host scope.
|
||||
|
@ -134,7 +134,7 @@ void Scope::fail(const std::string &msg) const {
|
|||
|
||||
const Scope *Scope::getSystemScope() const {
|
||||
for (const Scope *scope = this; scope; scope = scope->parent_scope_) {
|
||||
if (scope->kind_ == SK_SYSTEM) return scope;
|
||||
if (scope->kind_ == Kind::SK_SYSTEM) return scope;
|
||||
}
|
||||
fail("System scope not found");
|
||||
return nullptr;
|
||||
|
@ -142,7 +142,7 @@ const Scope *Scope::getSystemScope() const {
|
|||
|
||||
Scope *Scope::getGlobalScope() {
|
||||
for (auto scope = this; scope; scope = scope->parent_scope_) {
|
||||
if (scope->kind_ == SK_GLOBAL) return scope;
|
||||
if (scope->kind_ == Kind::SK_GLOBAL) return scope;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -151,16 +151,16 @@ const Scope *Scope::getGlobalScope() const {
|
|||
return const_cast<Scope *>(this)->getGlobalScope();
|
||||
}
|
||||
|
||||
Symbol *Scope::Lookup(const Identifier *name) {
|
||||
if (kind_ == SK_GLOBAL) return parent_scope_->Lookup(name);
|
||||
Symbol *Scope::Lookup(Identifier name) {
|
||||
if (kind_ == Kind::SK_GLOBAL) return parent_scope_->Lookup(name);
|
||||
|
||||
// TODO
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Symbol *Scope::LookupLocal(const Identifier *name) {
|
||||
if (kind_ == SK_GLOBAL) return nullptr;
|
||||
Symbol *Scope::LookupLocal(Identifier name) {
|
||||
if (kind_ == Kind::SK_GLOBAL) return nullptr;
|
||||
|
||||
auto &entries{this->entries_};
|
||||
for (auto it = entries.rbegin(); it != entries.rend(); ++it) {
|
||||
|
@ -171,7 +171,7 @@ Symbol *Scope::LookupLocal(const Identifier *name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Symbol *Scope::LookupProgramUnit(const Identifier *name) {
|
||||
Symbol *Scope::LookupProgramUnit(Identifier name) {
|
||||
Scope *scope = this->getGlobalScope();
|
||||
auto &entries{scope->entries_};
|
||||
|
||||
|
@ -187,20 +187,20 @@ Symbol *Scope::LookupProgramUnit(const Identifier *name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const Symbol *Scope::LookupProgramUnit(const Identifier *name) const {
|
||||
const Symbol *Scope::LookupProgramUnit(Identifier name) const {
|
||||
return const_cast<Scope *>(this)->LookupProgramUnit(name);
|
||||
}
|
||||
|
||||
Symbol *Scope::LookupModule(const Identifier *name) { return nullptr; }
|
||||
Symbol *Scope::LookupModule(Identifier name) { return nullptr; }
|
||||
|
||||
const Symbol *Scope::LookupModule(const Identifier *name) const {
|
||||
const Symbol *Scope::LookupModule(Identifier name) const {
|
||||
return const_cast<Scope *>(this)->LookupModule(name);
|
||||
}
|
||||
|
||||
int Scope::getId(void) const {
|
||||
if (this->kind_ == SK_SYSTEM)
|
||||
int Scope::id(void) const {
|
||||
if (this->kind_ == Kind::SK_SYSTEM)
|
||||
return 0;
|
||||
else if (this->kind_ == SK_GLOBAL)
|
||||
else if (this->kind_ == Kind::SK_GLOBAL)
|
||||
return 1;
|
||||
else
|
||||
return id_or_counter_;
|
||||
|
@ -216,7 +216,7 @@ std::string Scope::toString(void) {
|
|||
const char *info;
|
||||
switch (kind_) {
|
||||
#define SEMA_DEFINE_SCOPE(KIND, INFO) \
|
||||
case KIND: \
|
||||
case Kind::KIND: \
|
||||
info = INFO; \
|
||||
break;
|
||||
#include "flang/Sema/Scope.def"
|
||||
|
@ -225,10 +225,10 @@ std::string Scope::toString(void) {
|
|||
}
|
||||
|
||||
if (self_) {
|
||||
return std::string("#") + std::to_string(getId()) + " " + info + " (" +
|
||||
return std::string("#") + std::to_string(id()) + " " + info + " (" +
|
||||
self_->toString() + ")";
|
||||
} else {
|
||||
return std::string("#") + std::to_string(getId()) + " " + info +
|
||||
return std::string("#") + std::to_string(id()) + " " + info +
|
||||
" (***UNNAMED***)";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,18 @@
|
|||
namespace Fortran::semantics {
|
||||
|
||||
StatementMap::Entry &StatementMap::Get(Index index) {
|
||||
if (!((1 <= index) && (index <= Size()))) {
|
||||
FAIL("Illegal Stmt index " << index << " (expect 1.." << Size() << ")");
|
||||
if (!(( First() <= index) && (index <= Last()))) {
|
||||
FAIL("Illegal Stmt index " << index << " (expect "
|
||||
<< First() << " .." << Last() << ")");
|
||||
exit(1);
|
||||
}
|
||||
return entries_[index - 1];
|
||||
}
|
||||
|
||||
const StatementMap::Entry &StatementMap::Get(Index index) const {
|
||||
if (!((1 <= index) && (index <= Size()))) {
|
||||
FAIL("Illegal Stmt index " << index << " (expect 1.." << Size() << ")");
|
||||
if (!((First() <= index) && (index <= Last()))) {
|
||||
FAIL("Illegal Stmt index " << index << " (expect "
|
||||
<< First() << ".." << Last() << ")");
|
||||
exit(1);
|
||||
}
|
||||
return entries_[index - 1];
|
||||
|
@ -44,7 +46,7 @@ StatementMap::Index StatementMap::Add(StmtClass sclass, int label) {
|
|||
self.prev_in_construct = None;
|
||||
self.next_in_construct = None;
|
||||
|
||||
Index self_index = Size() + 1;
|
||||
Index self_index = Last() + 1;
|
||||
|
||||
if (Size() == 0) {
|
||||
// Special case of the first entry.
|
||||
|
@ -272,7 +274,7 @@ void StatementMap::Specialize( Index index, StmtClass oldc, StmtClass newc) {
|
|||
}
|
||||
|
||||
void StatementMap::DumpFlat(std::ostream &out, bool verbose) const {
|
||||
for (Index i = 1; i <= Size(); i++) {
|
||||
for (Index i = First() ; i <= Last(); i++) {
|
||||
out << std::setw(4) << std::right << i << ": ";
|
||||
DumpStmt(out, i, verbose);
|
||||
}
|
||||
|
@ -560,7 +562,7 @@ StatementMap::Index StatementMap::LastOfConstruct(
|
|||
// Visit all the statements that compose a construct.
|
||||
//
|
||||
// 'stmt' shall be a construct component (so in group Start, Part or End)
|
||||
void StatementMap::VisistConstruct(
|
||||
void StatementMap::VisitConstruct(
|
||||
StatementMap::Index stmt, std::function<bool(Index)> action) const {
|
||||
Index start = StartOfConstruct(stmt);
|
||||
for (Index at = start; at != None; at = NextInConstruct(at)) {
|
||||
|
@ -572,7 +574,7 @@ void StatementMap::VisistConstruct(
|
|||
//
|
||||
// 'stmt' shall be a construct component (so in group Start, Part or End)
|
||||
//
|
||||
void StatementMap::VisistConstructRev(
|
||||
void StatementMap::VisitConstructRev(
|
||||
Index stmt, std::function<bool(Index)> action) const {
|
||||
// Reminder: Using LastOfConstruct instead of EndOfConstruct
|
||||
// because the visitor shall usable while constructing
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
namespace Fortran::semantics {
|
||||
|
||||
Symbol::Symbol(ClassId cid, Scope *owner, const Identifier *name)
|
||||
: cid_(cid), owner_(owner), name_(name) {
|
||||
Symbol::Symbol(ClassId cid, Scope *owner, Identifier ident)
|
||||
: cid_(cid), owner_(owner), ident_(ident) {
|
||||
owner->add(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
|
||||
#include "flang/Sema/Scope.h"
|
||||
#include "flang/Sema/StatementMap.h"
|
||||
#include "flang/Sema/ParseTreeDump.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
|
||||
namespace psr = Fortran::parser ;
|
||||
namespace sm = Fortran::semantics ;
|
||||
|
@ -773,6 +775,7 @@ using SMap = sm::StatementMap;
|
|||
|
||||
namespace Fortran::parser {
|
||||
|
||||
|
||||
class Pass1 : public LabelTableStack
|
||||
{
|
||||
|
||||
|
@ -782,8 +785,8 @@ public:
|
|||
current_label_(-1) ,
|
||||
current_smap_(0)
|
||||
{
|
||||
system_scope_ = new Scope(Scope::SK_SYSTEM, nullptr, nullptr ) ;
|
||||
unit_scope_ = new Scope(Scope::SK_GLOBAL, system_scope_, nullptr) ;
|
||||
system_scope_ = new Scope(Scope::Kind::SK_SYSTEM, nullptr, nullptr ) ;
|
||||
unit_scope_ = new Scope(Scope::Kind::SK_GLOBAL, system_scope_, nullptr) ;
|
||||
current_scope_ = nullptr ;
|
||||
}
|
||||
|
||||
|
@ -799,7 +802,7 @@ public:
|
|||
Scope * current_scope_ ;
|
||||
SMap * current_smap_ ;
|
||||
|
||||
std::map<SMap::Index, const sm::Identifier *> construct_name_ ;
|
||||
std::map<SMap::Index, sm::Identifier> construct_name_ ;
|
||||
|
||||
// Provide all label-DO statements that are still open.
|
||||
// The key is the LabelDoStmt index
|
||||
|
@ -826,7 +829,7 @@ public:
|
|||
}
|
||||
|
||||
void LeaveScope(Scope::Kind k) {
|
||||
assert( current_scope_->getKind() == k ) ;
|
||||
assert( current_scope_->kind() == k ) ;
|
||||
TRACE("Leaving Scope " << current_scope_->toString() );
|
||||
current_scope_ = current_scope_->getParentScope() ;
|
||||
}
|
||||
|
@ -901,25 +904,24 @@ public:
|
|||
//
|
||||
// Should operate with Symbol instead of Identifier
|
||||
//
|
||||
const sm::Identifier * GetConstructName(SMap::Index stmt) {
|
||||
sm::OptIdentifier GetConstructName(SMap::Index stmt) {
|
||||
auto it = construct_name_.find(stmt);
|
||||
if ( it == construct_name_.end() ) {
|
||||
// Hummm... not sure because in order to handle EXIT and CYCLE
|
||||
// we will have to check the name of all parent constructs.
|
||||
INTERNAL_ERROR;
|
||||
return nullptr;
|
||||
return std::nullopt ;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//
|
||||
void
|
||||
SetConstructName(SMap::Index stmt, const sm::Identifier *name) {
|
||||
construct_name_[stmt] = name;
|
||||
SetConstructName(SMap::Index stmt, sm::OptIdentifier name) {
|
||||
if (name) {
|
||||
construct_name_.insert_or_assign(stmt, *name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CheckStatementName( SMap::Index part_or_end, const sm::Identifier *found, bool required) {
|
||||
CheckStatementName( SMap::Index part_or_end, sm::OptIdentifier found, bool required) {
|
||||
|
||||
auto & smap = GetStatementMap() ;
|
||||
|
||||
|
@ -929,13 +931,13 @@ public:
|
|||
SMap::Index start = smap.StartOfConstruct(part_or_end);
|
||||
assert( smap.GetGroup(start) == StmtGroup::Start );
|
||||
|
||||
const sm::Identifier * expect = GetConstructName(start);
|
||||
sm::OptIdentifier expect = GetConstructName(start);
|
||||
|
||||
// TODO: Get the location from part_or_end
|
||||
const char * text = StmtClassText( smap.GetClass(part_or_end) ) ;
|
||||
if ( expect ) {
|
||||
if ( found ) {
|
||||
if ( found != expect ) {
|
||||
if ( *found != *expect ) {
|
||||
FAIL("In statement #" << part_or_end
|
||||
<< ": Unexpected name '" << found->name() << "' in " << text
|
||||
<< "' (expected '" << expect->name() << "') ");
|
||||
|
@ -1264,13 +1266,15 @@ public:
|
|||
|
||||
template <typename T> bool Pre(const T &x) {
|
||||
if ( ENV("TRACE_FALLBACK") )
|
||||
TRACE( "*** fallback " << __PRETTY_FUNCTION__ ) ;
|
||||
TRACE( "*** fallback Pre(" << sm::GetTypeName(x) << ")" ) ;
|
||||
|
||||
// TRACE( "*** fallback " << __PRETTY_FUNCTION__ ) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
template <typename T> void Post(const T &) {
|
||||
if ( ENV("TRACE_FALLBACK") )
|
||||
TRACE( "*** fallback " << __PRETTY_FUNCTION__ ) ;
|
||||
// if ( ENV("TRACE_FALLBACK") )
|
||||
// TRACE( "*** fallback " << __PRETTY_FUNCTION__ ) ;
|
||||
}
|
||||
|
||||
// fallback for std::variant
|
||||
|
@ -1399,29 +1403,27 @@ public:
|
|||
|
||||
|
||||
sm::ProgramSymbol * symbol{0};
|
||||
const ProgramStmt * program_stmt = GetOptValue( std::get<x.PROG>(x.t) ) ;
|
||||
const ProgramStmt * program_stmt = GetOptValue( std::get<x.PROG>(x.t) ) ;
|
||||
|
||||
const sm::Identifier * program_ident{0};
|
||||
sm::OptIdentifier program_ident;
|
||||
|
||||
if ( program_stmt ) {
|
||||
const std::string & name = program_stmt->v ;
|
||||
TRACE("program name = " << name ) ;
|
||||
program_ident = sm::Identifier::get(name) ;
|
||||
symbol = new sm::ProgramSymbol( current_scope_, program_ident ) ;
|
||||
program_ident = sm::Identifier::make(program_stmt->v) ;
|
||||
symbol = new sm::ProgramSymbol( current_scope_, *program_ident ) ;
|
||||
TraceStatementInfo( std::get<x.PROG>(x.t) ) ;
|
||||
}
|
||||
|
||||
// TODO: Should we create a symbol when there is no PROGRAM statement?
|
||||
|
||||
// Install the scope
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::SK_PROGRAM, current_scope_, symbol) ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::Kind::SK_PROGRAM, current_scope_, symbol) ) ;
|
||||
|
||||
// Install the label table
|
||||
sema.label_table = PushLabelTable( new LabelTable ) ;
|
||||
|
||||
// Check the name consistancy
|
||||
// const std::string * end_name = GetOptValue(end_stmt.v) ;
|
||||
// const sm::Identifier * end_ident = end_name ? sm::Identifier::get(*end_name) : nullptr ;
|
||||
// sm::Identifier end_ident = end_name ? sm::Identifier::get(*end_name) : nullptr ;
|
||||
|
||||
// CheckStatementName(program_ident,end_ident,"program",false) ;
|
||||
|
||||
|
@ -1432,7 +1434,7 @@ public:
|
|||
// } else if ( program_ident ) {
|
||||
// FAIL("Unexpected end program name '" << end_ident->name() << "'");
|
||||
// }
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -1440,7 +1442,7 @@ public:
|
|||
auto &sema = getSema(x);
|
||||
GetLabelTable().dump() ;
|
||||
PopLabelTable(sema.label_table) ;
|
||||
LeaveScope(Scope::SK_PROGRAM) ;
|
||||
LeaveScope(Scope::Kind::SK_PROGRAM) ;
|
||||
TRACE_CALL() ;
|
||||
}
|
||||
|
||||
|
@ -1454,22 +1456,22 @@ public:
|
|||
// const EndFunctionStmt & end_stmt = GetValue(std::get<x.END>(x.t)) ;
|
||||
|
||||
const std::string &function_name = std::get<1>(function_stmt.t) ;
|
||||
const sm::Identifier *function_ident = sm::Identifier::get(function_name) ;
|
||||
sm::Identifier function_ident = sm::Identifier::make(function_name) ;
|
||||
|
||||
// TODO: lookup for name conflict
|
||||
sm::Symbol *lookup ;
|
||||
if ( current_scope_->getKind() == Scope::SK_GLOBAL ) {
|
||||
if ( current_scope_->kind() == Scope::Kind::SK_GLOBAL ) {
|
||||
lookup = current_scope_->LookupProgramUnit(function_ident) ;
|
||||
if (lookup) FAIL("A unit '" << function_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << function_ident.name() << "' is already declared") ;
|
||||
} else {
|
||||
lookup = current_scope_->LookupLocal(function_ident) ;
|
||||
// TODO: There are a few cases, a function redeclaration is not necessarily a problem.
|
||||
// A typical example is a PRIVATE or PUBLIC statement in a module
|
||||
if (lookup) FAIL("A unit '" << function_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << function_ident.name() << "' is already declared") ;
|
||||
}
|
||||
|
||||
auto symbol = new sm::FunctionSymbol( current_scope_, function_ident ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::SK_FUNCTION, current_scope_, symbol) ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::Kind::SK_FUNCTION, current_scope_, symbol) ) ;
|
||||
|
||||
// Install the label table
|
||||
sema.label_table = PushLabelTable( new LabelTable ) ;
|
||||
|
@ -1478,7 +1480,7 @@ public:
|
|||
|
||||
// Check the end function name
|
||||
//const std::string * end_name = GetOptValue(end_stmt.v) ;
|
||||
// const sm::Identifier * end_ident = end_name ? sm::Identifier::get(*end_name) : nullptr ;
|
||||
// sm::Identifier end_ident = end_name ? sm::Identifier::make(*end_name) : nullptr ;
|
||||
|
||||
// CheckStatementName(function_ident,end_ident,"function",false) ;
|
||||
|
||||
|
@ -1490,7 +1492,7 @@ public:
|
|||
auto &sema = getSema(x);
|
||||
GetLabelTable().dump() ;
|
||||
PopLabelTable(sema.label_table) ;
|
||||
LeaveScope(Scope::SK_FUNCTION) ;
|
||||
LeaveScope(Scope::Kind::SK_FUNCTION) ;
|
||||
}
|
||||
|
||||
// ========== SubroutineSubprogram ===========
|
||||
|
@ -1503,22 +1505,22 @@ public:
|
|||
// const EndSubroutineStmt & end_stmt = GetValue(std::get<x.END>(x.t)) ;
|
||||
|
||||
const std::string &subroutine_name = std::get<1>(subroutine_stmt.t) ;
|
||||
const sm::Identifier *subroutine_ident = sm::Identifier::get(subroutine_name) ;
|
||||
sm::Identifier subroutine_ident = sm::Identifier::make(subroutine_name) ;
|
||||
|
||||
// TODO: lookup for name conflict
|
||||
sm::Symbol *lookup ;
|
||||
if ( current_scope_->getKind() == Scope::SK_GLOBAL ) {
|
||||
if ( current_scope_->kind() == Scope::Kind::SK_GLOBAL ) {
|
||||
lookup = current_scope_->LookupProgramUnit(subroutine_ident) ;
|
||||
if (lookup) FAIL("A unit '" << subroutine_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << subroutine_ident.name() << "' is already declared") ;
|
||||
} else {
|
||||
lookup = current_scope_->LookupLocal(subroutine_ident) ;
|
||||
// TODO: There are a few cases, a subroutine redeclaration is not necessarily a problem.
|
||||
// A typical example is a PRIVATE or PUBLIC statement in a module
|
||||
if (lookup) FAIL("A unit '" << subroutine_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << subroutine_ident.name() << "' is already declared") ;
|
||||
}
|
||||
|
||||
auto symbol = new sm::SubroutineSymbol( current_scope_, subroutine_ident ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::SK_SUBROUTINE, current_scope_, symbol) ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::Kind::SK_SUBROUTINE, current_scope_, symbol) ) ;
|
||||
|
||||
// Install the label table
|
||||
sema.label_table = PushLabelTable( new LabelTable ) ;
|
||||
|
@ -1527,7 +1529,7 @@ public:
|
|||
|
||||
// Check the end subroutine name
|
||||
// const std::string * end_name = GetOptValue(end_stmt.v) ;
|
||||
// const sm::Identifier * end_ident = end_name ? sm::Identifier::get(*end_name) : nullptr ;
|
||||
// sm::Identifier end_ident = end_name ? sm::Identifier::make(*end_name) : nullptr ;
|
||||
|
||||
// CheckStatementName(subroutine_ident,end_ident,"subroutine",false) ;
|
||||
return true ;
|
||||
|
@ -1540,7 +1542,7 @@ public:
|
|||
PopLabelTable(sema.label_table) ;
|
||||
if ( ! opened_label_do_.empty() )
|
||||
INTERNAL_ERROR;
|
||||
LeaveScope(Scope::SK_SUBROUTINE) ;
|
||||
LeaveScope(Scope::Kind::SK_SUBROUTINE) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1554,22 +1556,22 @@ public:
|
|||
// const EndModuleStmt & end_stmt = GetValue(std::get<x.END>(x.t)) ;
|
||||
|
||||
const std::string &module_name = module_stmt.v ;
|
||||
const sm::Identifier *module_ident = sm::Identifier::get(module_name) ;
|
||||
sm::Identifier module_ident = sm::Identifier::make(module_name) ;
|
||||
|
||||
// TODO: lookup for name conflict
|
||||
sm::Symbol *lookup ;
|
||||
if ( current_scope_->getKind() == Scope::SK_GLOBAL ) {
|
||||
if ( current_scope_->kind() == Scope::Kind::SK_GLOBAL ) {
|
||||
lookup = current_scope_->LookupProgramUnit(module_ident) ;
|
||||
if (lookup) FAIL("A unit '" << module_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << module_ident.name() << "' is already declared") ;
|
||||
} else {
|
||||
lookup = current_scope_->LookupLocal(module_ident) ;
|
||||
// TODO: There are a few cases, a module redeclaration is not necessarily a problem.
|
||||
// A typical example is a PRIVATE or PUBLIC statement in a module
|
||||
if (lookup) FAIL("A unit '" << module_ident->name() << "' is already declared") ;
|
||||
if (lookup) FAIL("A unit '" << module_ident.name() << "' is already declared") ;
|
||||
}
|
||||
|
||||
auto symbol = new sm::ModuleSymbol( current_scope_, module_ident ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::SK_MODULE, current_scope_, symbol) ) ;
|
||||
sema.scope_provider = EnterScope( new Scope(Scope::Kind::SK_MODULE, current_scope_, symbol) ) ;
|
||||
|
||||
// Install the label table
|
||||
sema.label_table = PushLabelTable( new LabelTable ) ;
|
||||
|
@ -1578,7 +1580,7 @@ public:
|
|||
|
||||
// Check the end module name
|
||||
// const std::string * end_name = GetOptValue(end_stmt.v) ;
|
||||
// const sm::Identifier * end_ident = end_name ? sm::Identifier::get(*end_name) : nullptr ;
|
||||
// sm::Identifier end_ident = end_name ? sm::Identifier::make(*end_name) : nullptr ;
|
||||
|
||||
// CheckStatementName(module_ident,end_ident,"module",false) ;
|
||||
|
||||
|
@ -1590,7 +1592,7 @@ public:
|
|||
auto &sema = getSema(x);
|
||||
GetLabelTable().dump() ;
|
||||
PopLabelTable(sema.label_table) ;
|
||||
LeaveScope(Scope::SK_MODULE) ;
|
||||
LeaveScope(Scope::Kind::SK_MODULE) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1626,7 +1628,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::DerivedType);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -1642,7 +1644,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndType);
|
||||
|
||||
auto name = sm::Identifier::get(x.v) ;
|
||||
auto name = sm::Identifier::make(x.v) ;
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -1658,7 +1660,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Module);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -1674,7 +1676,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::EndModule);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -1690,7 +1692,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Subroutine);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -1706,7 +1708,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::EndSubroutine);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
return true ;
|
||||
}
|
||||
|
@ -1717,7 +1719,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Function);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -1733,7 +1735,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::EndFunction);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -1797,6 +1799,8 @@ public:
|
|||
bool Pre(const AssignmentStmt &x) {
|
||||
TRACE_CALL() ;
|
||||
InitStmt(x, StmtClass::Assignment);
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -1810,9 +1814,10 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Program);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -1826,7 +1831,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema =InitStmt(x, StmtClass::EndProgram);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -2127,7 +2132,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Block);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2144,7 +2149,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndBlock);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2161,7 +2166,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::ForallConstruct);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2178,7 +2183,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndForall);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2196,7 +2201,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Associate);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2213,7 +2218,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndAssociate);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2229,7 +2234,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::ChangeTeam);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2245,7 +2250,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndChangeTeam);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2261,7 +2266,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::Critical);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2277,7 +2282,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndCritical);
|
||||
|
||||
auto name = sm::Identifier::get(x.v) ;
|
||||
auto name = sm::Identifier::make(x.v) ;
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2357,7 +2362,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::IfThen);
|
||||
|
||||
auto name = sm::Identifier::get( std::get<0>(x.t) );
|
||||
auto name = sm::Identifier::make( std::get<0>(x.t) );
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2373,7 +2378,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::ElseIf);
|
||||
|
||||
auto name = sm::Identifier::get( std::get<1>(x.t) );
|
||||
auto name = sm::Identifier::make( std::get<1>(x.t) );
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -2389,7 +2394,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::Else);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -2405,7 +2410,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndIf);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2421,7 +2426,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::NonLabelDo);
|
||||
|
||||
auto name = sm::Identifier::get( std::get<0>(x.t) );
|
||||
auto name = sm::Identifier::make( std::get<0>(x.t) );
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
// Specialize from StmtClass::LabelDo to StmtClass::NonLabelDoWhile or
|
||||
|
@ -2457,7 +2462,7 @@ public:
|
|||
}
|
||||
|
||||
// And also record the construct name
|
||||
auto name = sm::Identifier::get( std::get<0>(x.t) );
|
||||
auto name = sm::Identifier::make( std::get<0>(x.t) );
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
// Specialize from StmtClass::LabelDo to StmtClass::LabelDoWhile or
|
||||
|
@ -2477,7 +2482,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::EndDo);
|
||||
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2507,7 +2512,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::SelectCase);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2536,7 +2541,7 @@ public:
|
|||
#if 1
|
||||
// Method 1: Manually visit the construct elements
|
||||
// smap.VisistConstruct( sema.stmt_index,
|
||||
smap.VisistConstructRev( sema.stmt_index,
|
||||
smap.VisitConstructRev( sema.stmt_index,
|
||||
[&]( SMap::Index at ) -> bool
|
||||
{
|
||||
if ( smap.GetClass(at) == StmtClass::CaseDefault ) {
|
||||
|
@ -2563,7 +2568,7 @@ public:
|
|||
}
|
||||
|
||||
// Check the construct name
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
return true ;
|
||||
|
@ -2581,7 +2586,7 @@ public:
|
|||
auto &sema = InitStmt(x, StmtClass::EndSelect);
|
||||
|
||||
// Check the construct name
|
||||
auto name = sm::Identifier::get(x.v);
|
||||
auto name = sm::Identifier::make(x.v);
|
||||
CheckStatementName(sema.stmt_index, name, true);
|
||||
|
||||
return true ;
|
||||
|
@ -2597,7 +2602,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto & sema = InitStmt(x, StmtClass::SelectRank);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2670,7 +2675,7 @@ public:
|
|||
|
||||
|
||||
// Check the construct name
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
|
||||
|
@ -2687,7 +2692,7 @@ public:
|
|||
TRACE_CALL() ;
|
||||
auto &sema = InitStmt(x, StmtClass::SelectType);
|
||||
|
||||
auto name = sm::Identifier::get(std::get<0>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<0>(x.t));
|
||||
SetConstructName(sema.stmt_index, name);
|
||||
|
||||
return true ;
|
||||
|
@ -2756,7 +2761,7 @@ public:
|
|||
}
|
||||
|
||||
// Check the construct name.
|
||||
auto name = sm::Identifier::get(std::get<1>(x.t));
|
||||
auto name = sm::Identifier::make(std::get<1>(x.t));
|
||||
CheckStatementName(sema.stmt_index, name, false);
|
||||
|
||||
|
||||
|
@ -2959,7 +2964,7 @@ public:
|
|||
auto & smap = GetStatementMap() ;
|
||||
|
||||
// the name of the construct we are looking for (can be null)
|
||||
const sm::Identifier * target_name = sm::Identifier::get(x.v) ;
|
||||
sm::OptIdentifier target_name = sm::Identifier::make(x.v) ;
|
||||
|
||||
// Reminder: Unlike in EXIT, the target of a CYCLE statement is always
|
||||
// a DO so the target resolution are similar but not identical.
|
||||
|
@ -3082,7 +3087,7 @@ public:
|
|||
auto & smap = GetStatementMap() ;
|
||||
|
||||
// the name of the construct we are looking for (can be null)
|
||||
const sm::Identifier * target_name = sm::Identifier::get(x.v) ;
|
||||
sm::OptIdentifier target_name = sm::Identifier::make(x.v) ;
|
||||
|
||||
// Remark: I am currently search the target construct by
|
||||
// only considering its identifer but this is actually incorrect
|
||||
|
@ -3520,6 +3525,7 @@ public:
|
|||
bool Pre(const AssignStmt &x) {
|
||||
TRACE_CALL() ;
|
||||
InitStmt(x, StmtClass::Assign);
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -3622,7 +3628,9 @@ void DoSemanticAnalysis( const psr::Program &all)
|
|||
psr::Pass1 pass1 ;
|
||||
for (const psr::ProgramUnit &unit : all.v) {
|
||||
TRACE("===========================================================================================================");
|
||||
pass1.run(unit) ;
|
||||
psr::DumpTree(unit);
|
||||
TRACE("===========================================================================================================");
|
||||
pass1.run(unit) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue