2018-03-23 01:08:20 +01:00
|
|
|
#ifndef FORTRAN_SEMANTICS_SYMBOL_H_
|
|
|
|
#define FORTRAN_SEMANTICS_SYMBOL_H_
|
|
|
|
|
|
|
|
#include "type.h"
|
|
|
|
#include <functional>
|
2018-03-23 20:24:29 +01:00
|
|
|
#include <memory>
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
namespace Fortran::semantics {
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-04-11 22:11:42 +02:00
|
|
|
/// A SourceName is a name in the cooked character stream,
|
2018-04-12 21:59:42 +02:00
|
|
|
/// i.e. a range of lower-case characters with provenance.
|
2018-04-11 22:11:42 +02:00
|
|
|
using SourceName = parser::CharBlock;
|
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
/// A Symbol consists of common information (name, owner, and attributes)
|
|
|
|
/// and details information specific to the kind of symbol, represented by the
|
|
|
|
/// *Details classes.
|
|
|
|
|
|
|
|
class Scope;
|
2018-04-17 23:16:42 +02:00
|
|
|
class Symbol;
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
class ModuleDetails {
|
|
|
|
public:
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
|
|
class MainProgramDetails {
|
|
|
|
public:
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
|
|
class SubprogramDetails {
|
|
|
|
public:
|
2018-04-11 22:11:42 +02:00
|
|
|
SubprogramDetails() {}
|
2018-04-17 23:16:42 +02:00
|
|
|
SubprogramDetails(const SubprogramDetails &that)
|
|
|
|
: dummyArgs_{that.dummyArgs_}, result_{that.result_} {}
|
|
|
|
|
|
|
|
bool isFunction() const { return result_.has_value(); }
|
|
|
|
const Symbol &result() const { CHECK(isFunction()); return **result_; }
|
|
|
|
void set_result(Symbol &result) {
|
|
|
|
CHECK(!result_.has_value());
|
|
|
|
result_ = &result;
|
|
|
|
}
|
|
|
|
const std::list<Symbol *> &dummyArgs() const { return dummyArgs_; }
|
|
|
|
void add_dummyArg(Symbol &symbol) { dummyArgs_.push_back(&symbol); }
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
private:
|
2018-04-17 23:16:42 +02:00
|
|
|
std::list<Symbol *> dummyArgs_;
|
|
|
|
std::optional<Symbol *> result_;
|
2018-03-23 01:08:20 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const SubprogramDetails &);
|
|
|
|
};
|
|
|
|
|
|
|
|
class EntityDetails {
|
|
|
|
public:
|
|
|
|
EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
|
|
|
|
const std::optional<DeclTypeSpec> &type() const { return type_; }
|
2018-04-12 21:59:42 +02:00
|
|
|
void set_type(const DeclTypeSpec &type);
|
|
|
|
const ArraySpec &shape() const { return shape_; }
|
|
|
|
void set_shape(const ArraySpec &shape);
|
2018-03-23 01:08:20 +01:00
|
|
|
bool isDummy() const { return isDummy_; }
|
2018-04-17 23:16:42 +02:00
|
|
|
bool isArray() const { return !shape_.empty(); }
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool isDummy_;
|
|
|
|
std::optional<DeclTypeSpec> type_;
|
2018-04-12 21:59:42 +02:00
|
|
|
ArraySpec shape_;
|
2018-03-23 01:08:20 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const EntityDetails &);
|
|
|
|
};
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
class UnknownDetails {};
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
class Symbol {
|
|
|
|
public:
|
2018-03-23 20:24:29 +01:00
|
|
|
// TODO: more kinds of details
|
|
|
|
using Details = std::variant<UnknownDetails, MainProgramDetails,
|
|
|
|
ModuleDetails, SubprogramDetails, EntityDetails>;
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-04-11 22:11:42 +02:00
|
|
|
Symbol(const Scope &owner, const SourceName &name, const Attrs &attrs,
|
2018-03-23 20:24:29 +01:00
|
|
|
Details &&details)
|
2018-04-17 23:16:42 +02:00
|
|
|
: owner_{owner}, attrs_{attrs}, details_{std::move(details)} {
|
|
|
|
add_occurrence(name);
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
const Scope &owner() const { return owner_; }
|
2018-04-17 23:16:42 +02:00
|
|
|
const SourceName &name() const { return occurrences_.front(); }
|
2018-03-30 22:57:23 +02:00
|
|
|
Attrs &attrs() { return attrs_; }
|
2018-03-23 01:08:20 +01:00
|
|
|
const Attrs &attrs() const { return attrs_; }
|
|
|
|
|
|
|
|
// Does symbol have this type of details?
|
|
|
|
template<typename D> bool has() const {
|
|
|
|
return std::holds_alternative<D>(details_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return a non-owning pointer to details if it is type D, else nullptr.
|
|
|
|
template<typename D> D *detailsIf() { return std::get_if<D>(&details_); }
|
2018-04-11 22:11:42 +02:00
|
|
|
template<typename D> const D *detailsIf() const {
|
|
|
|
return std::get_if<D>(&details_);
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
// Return a reference to the details which must be of type D.
|
|
|
|
template<typename D> D &details() {
|
2018-04-17 23:16:42 +02:00
|
|
|
return const_cast<D &>(static_cast<const Symbol *>(this)->details<D>());
|
2018-03-23 01:08:20 +01:00
|
|
|
}
|
|
|
|
template<typename D> const D &details() const {
|
2018-04-17 23:16:42 +02:00
|
|
|
if (const auto p = detailsIf<D>()) {
|
|
|
|
return *p;
|
|
|
|
} else {
|
|
|
|
Fortran::parser::die("unexpected %s details at %s(%d)",
|
|
|
|
GetDetailsName().c_str(), __FILE__, __LINE__);
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Assign the details of the symbol from one of the variants.
|
|
|
|
// Only allowed if unknown.
|
2018-03-30 22:57:23 +02:00
|
|
|
void set_details(Details &&details) {
|
2018-03-23 01:08:20 +01:00
|
|
|
CHECK(has<UnknownDetails>());
|
2018-03-30 22:57:23 +02:00
|
|
|
details_.swap(details);
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-04-17 23:16:42 +02:00
|
|
|
const std::list<SourceName> &occurrences() const {
|
|
|
|
return occurrences_;
|
|
|
|
}
|
|
|
|
void add_occurrence(const SourceName &name) {
|
|
|
|
occurrences_.push_back(name);
|
|
|
|
}
|
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
private:
|
|
|
|
const Scope &owner_;
|
2018-04-17 23:16:42 +02:00
|
|
|
std::list<SourceName> occurrences_;
|
2018-03-30 22:57:23 +02:00
|
|
|
Attrs attrs_;
|
2018-03-23 01:08:20 +01:00
|
|
|
Details details_;
|
2018-04-17 23:16:42 +02:00
|
|
|
|
|
|
|
const std::string GetDetailsName() const;
|
2018-03-23 01:08:20 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const Symbol &);
|
|
|
|
};
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
} // namespace Fortran::semantics
|
2018-03-23 01:08:20 +01:00
|
|
|
#endif // FORTRAN_SEMANTICS_SYMBOL_H_
|