[flang] Add ENUM_CLASS to define enum class with ToString function.
This replaces DEFINE_NESTED_ENUM_CLASS in parse-tree.h but works similarly. "ENUM_CLASS(Foo, A, B, C)" defined enum class Foo with enumerators A, B, C. It also defines an overloading of EnumToString that converts enumerators to their string representation. Change unparse.cc to adapt to this change. Make use of ENUM_CLASS in attr.h and attr.cc. Original-commit: flang-compiler/f18@c45b8f172a Reviewed-on: https://github.com/flang-compiler/f18/pull/31
This commit is contained in:
@@ -15,5 +15,24 @@ namespace parser {
|
||||
fputc('\n', stderr);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// Convert the int index of an enumerator to a string.
|
||||
// enumNames is a list of the names, separated by commas with optional spaces.
|
||||
// This is intended for use from the expansion of ENUM_CLASS.
|
||||
std::string EnumIndexToString(int index, const char *enumNames) {
|
||||
const char *p{enumNames};
|
||||
for (; index > 0; --index, ++p) {
|
||||
for (; *p && *p != ','; ++p) {
|
||||
}
|
||||
}
|
||||
for (; *p == ' '; ++p) {
|
||||
}
|
||||
CHECK(*p != '\0');
|
||||
const char *q = p;
|
||||
for (; *q && *q != ' ' && *q != ','; ++q) {
|
||||
}
|
||||
return std::string(p, q - p);
|
||||
}
|
||||
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
|
||||
@@ -102,6 +102,16 @@ template<typename A> struct BadType : std::false_type {};
|
||||
} \
|
||||
} \
|
||||
template<typename A> constexpr bool T { class_trait_ns_##T::trait_value<A>() }
|
||||
|
||||
// Define enum class NAME with the given enumerators, and also a
|
||||
// static function EnumToString that maps enumerators to std::string.
|
||||
std::string EnumIndexToString(int index, const char *names);
|
||||
#define ENUM_CLASS(NAME, ...) \
|
||||
enum class NAME { __VA_ARGS__ }; \
|
||||
static inline std::string EnumToString(NAME e) \
|
||||
{ return Fortran::parser::EnumIndexToString( \
|
||||
static_cast<int>(e), #__VA_ARGS__); }
|
||||
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
#endif // FORTRAN_PARSER_IDIOMS_H_
|
||||
|
||||
@@ -94,14 +94,6 @@ CLASS_TRAIT(TupleTrait);
|
||||
WRAPPER_CLASS_BOILERPLATE(classname, type); \
|
||||
}
|
||||
|
||||
// Enumeration types in classes can be defined with this macro,
|
||||
// which also captures the names of the enums for formatting.
|
||||
// Invocations an be followed by declarators and must be followed by
|
||||
// a semicolon.
|
||||
#define DEFINE_NESTED_ENUM_CLASS(ENUMTYPE, ...) \
|
||||
static constexpr const char *ENUMTYPE##AsString{#__VA_ARGS__}; \
|
||||
enum class ENUMTYPE { __VA_ARGS__ }
|
||||
|
||||
namespace Fortran {
|
||||
namespace parser {
|
||||
|
||||
@@ -517,8 +509,8 @@ WRAPPER_CLASS(DefinedOpName, Name);
|
||||
// R610 extended-intrinsic-op -> intrinsic-operator
|
||||
struct DefinedOperator {
|
||||
UNION_CLASS_BOILERPLATE(DefinedOperator);
|
||||
DEFINE_NESTED_ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add,
|
||||
Subtract, Concat, LT, LE, EQ, NE, GE, GT, NOT, AND, OR, XOR, EQV, NEQV);
|
||||
ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat,
|
||||
LT, LE, EQ, NE, GE, GT, NOT, AND, OR, XOR, EQV, NEQV)
|
||||
std::variant<DefinedOpName, IntrinsicOperator> u;
|
||||
};
|
||||
|
||||
@@ -530,10 +522,11 @@ using ObjectName = Name;
|
||||
// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
|
||||
struct ImportStmt {
|
||||
BOILERPLATE(ImportStmt);
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Default, Only, None, All) kind{Kind::Default};
|
||||
ENUM_CLASS(Kind, Default, Only, None, All)
|
||||
ImportStmt(Kind &&k) : kind{k} {}
|
||||
ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
|
||||
ImportStmt(Kind &&, std::list<Name> &&);
|
||||
Kind kind{Kind::Default};
|
||||
std::list<Name> names;
|
||||
};
|
||||
|
||||
@@ -802,7 +795,7 @@ struct ConstantValue {
|
||||
|
||||
// R807 access-spec -> PUBLIC | PRIVATE
|
||||
struct AccessSpec {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Public, Private);
|
||||
ENUM_CLASS(Kind, Public, Private)
|
||||
WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
|
||||
};
|
||||
|
||||
@@ -846,7 +839,7 @@ struct TypeParamDecl {
|
||||
// integer-type-spec , type-param-attr-spec :: type-param-decl-list
|
||||
// R734 type-param-attr-spec -> KIND | LEN
|
||||
struct TypeParamDefStmt {
|
||||
DEFINE_NESTED_ENUM_CLASS(KindOrLen, Kind, Len); // R734
|
||||
ENUM_CLASS(KindOrLen, Kind, Len) // R734
|
||||
TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
|
||||
std::tuple<IntegerTypeSpec, KindOrLen, std::list<TypeParamDecl>> t;
|
||||
};
|
||||
@@ -1226,7 +1219,7 @@ struct ArraySpec {
|
||||
|
||||
// R826 intent-spec -> IN | OUT | INOUT
|
||||
struct IntentSpec {
|
||||
DEFINE_NESTED_ENUM_CLASS(Intent, In, Out, InOut);
|
||||
ENUM_CLASS(Intent, In, Out, InOut)
|
||||
WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
|
||||
};
|
||||
|
||||
@@ -1303,7 +1296,7 @@ WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>);
|
||||
// R833 bind-entity -> entity-name | / common-block-name /
|
||||
struct BindEntity {
|
||||
TUPLE_CLASS_BOILERPLATE(BindEntity);
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Object, Common);
|
||||
ENUM_CLASS(Kind, Object, Common)
|
||||
std::tuple<Kind, Name> t;
|
||||
};
|
||||
|
||||
@@ -1430,7 +1423,7 @@ WRAPPER_CLASS(ProtectedStmt, std::list<Name>);
|
||||
// R858 proc-pointer-name -> name
|
||||
struct SavedEntity {
|
||||
TUPLE_CLASS_BOILERPLATE(SavedEntity);
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Object, ProcPointer, Common);
|
||||
ENUM_CLASS(Kind, Object, ProcPointer, Common)
|
||||
std::tuple<Kind, Name> t;
|
||||
};
|
||||
|
||||
@@ -1464,7 +1457,7 @@ struct ImplicitSpec {
|
||||
// R866 implicit-name-spec -> EXTERNAL | TYPE
|
||||
struct ImplicitStmt {
|
||||
UNION_CLASS_BOILERPLATE(ImplicitStmt);
|
||||
DEFINE_NESTED_ENUM_CLASS(ImplicitNoneNameSpec, External, Type); // R866
|
||||
ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
|
||||
std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
|
||||
};
|
||||
|
||||
@@ -2353,7 +2346,7 @@ struct StopCode {
|
||||
// R1161 error-stop-stmt ->
|
||||
// ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
|
||||
struct StopStmt {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Stop, ErrorStop);
|
||||
ENUM_CLASS(Kind, Stop, ErrorStop)
|
||||
TUPLE_CLASS_BOILERPLATE(StopStmt);
|
||||
std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
|
||||
};
|
||||
@@ -2469,9 +2462,8 @@ WRAPPER_CLASS(ErrLabel, Label);
|
||||
struct ConnectSpec {
|
||||
UNION_CLASS_BOILERPLATE(ConnectSpec);
|
||||
struct CharExpr {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal,
|
||||
Delim, Encoding, Form, Pad, Position, Round, Sign,
|
||||
Dispose /*extension*/);
|
||||
ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
|
||||
Encoding, Form, Pad, Position, Round, Sign, Dispose /*extension*/)
|
||||
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
||||
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
||||
};
|
||||
@@ -2526,8 +2518,7 @@ WRAPPER_CLASS(EorLabel, Label);
|
||||
struct IoControlSpec {
|
||||
UNION_CLASS_BOILERPLATE(IoControlSpec);
|
||||
struct CharExpr {
|
||||
DEFINE_NESTED_ENUM_CLASS(
|
||||
Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign);
|
||||
ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign)
|
||||
TUPLE_CLASS_BOILERPLATE(CharExpr);
|
||||
std::tuple<Kind, ScalarDefaultCharExpr> t;
|
||||
};
|
||||
@@ -2680,20 +2671,19 @@ WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>);
|
||||
struct InquireSpec {
|
||||
UNION_CLASS_BOILERPLATE(InquireSpec);
|
||||
struct CharVar {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal,
|
||||
Delim, Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position,
|
||||
Read, Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted,
|
||||
Write);
|
||||
ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
|
||||
Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
|
||||
Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write)
|
||||
TUPLE_CLASS_BOILERPLATE(CharVar);
|
||||
std::tuple<Kind, ScalarDefaultCharVariable> t;
|
||||
};
|
||||
struct IntVar {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size);
|
||||
ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size)
|
||||
TUPLE_CLASS_BOILERPLATE(IntVar);
|
||||
std::tuple<Kind, ScalarIntVariable> t;
|
||||
};
|
||||
struct LogVar {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, Exist, Named, Opened, Pending);
|
||||
ENUM_CLASS(Kind, Exist, Named, Opened, Pending)
|
||||
TUPLE_CLASS_BOILERPLATE(LogVar);
|
||||
std::tuple<Kind, Scalar<Logical<Variable>>> t;
|
||||
};
|
||||
@@ -2866,7 +2856,7 @@ struct Only {
|
||||
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
|
||||
struct UseStmt {
|
||||
BOILERPLATE(UseStmt);
|
||||
DEFINE_NESTED_ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic); // R1410
|
||||
ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
|
||||
template<typename A>
|
||||
UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
|
||||
: nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
|
||||
@@ -2979,7 +2969,7 @@ struct InterfaceBody {
|
||||
|
||||
// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
|
||||
struct ProcedureStmt {
|
||||
DEFINE_NESTED_ENUM_CLASS(Kind, ModuleProcedure, Procedure);
|
||||
ENUM_CLASS(Kind, ModuleProcedure, Procedure)
|
||||
TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
|
||||
std::tuple<Kind, std::list<Name>> t;
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
case DefinedOperator::IntrinsicOperator::GT: Put('>'); break;
|
||||
default:
|
||||
Put('.');
|
||||
PutEnum(static_cast<int>(x), DefinedOperator::IntrinsicOperatorAsString);
|
||||
Word(DefinedOperator::EnumToString(x));
|
||||
Put('.');
|
||||
}
|
||||
return false;
|
||||
@@ -1994,22 +1994,22 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
#define WALK_NESTED_ENUM(ENUMTYPE) \
|
||||
bool Pre(const ENUMTYPE &x) { \
|
||||
PutEnum(static_cast<int>(x), ENUMTYPE##AsString); \
|
||||
#define WALK_NESTED_ENUM(CLASS, ENUM) \
|
||||
bool Pre(const CLASS::ENUM &x) { \
|
||||
Word(CLASS::EnumToString(x)); \
|
||||
return false; \
|
||||
}
|
||||
WALK_NESTED_ENUM(AccessSpec::Kind) // R807
|
||||
WALK_NESTED_ENUM(TypeParamDefStmt::KindOrLen) // R734
|
||||
WALK_NESTED_ENUM(IntentSpec::Intent) // R826
|
||||
WALK_NESTED_ENUM(ImplicitStmt::ImplicitNoneNameSpec) // R866
|
||||
WALK_NESTED_ENUM(ConnectSpec::CharExpr::Kind) // R1205
|
||||
WALK_NESTED_ENUM(IoControlSpec::CharExpr::Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::CharVar::Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::IntVar::Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::LogVar::Kind)
|
||||
WALK_NESTED_ENUM(ProcedureStmt::Kind) // R1506
|
||||
WALK_NESTED_ENUM(UseStmt::ModuleNature) // R1410
|
||||
WALK_NESTED_ENUM(AccessSpec, Kind) // R807
|
||||
WALK_NESTED_ENUM(TypeParamDefStmt, KindOrLen) // R734
|
||||
WALK_NESTED_ENUM(IntentSpec, Intent) // R826
|
||||
WALK_NESTED_ENUM(ImplicitStmt, ImplicitNoneNameSpec) // R866
|
||||
WALK_NESTED_ENUM(ConnectSpec::CharExpr, Kind) // R1205
|
||||
WALK_NESTED_ENUM(IoControlSpec::CharExpr, Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::CharVar, Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::IntVar, Kind)
|
||||
WALK_NESTED_ENUM(InquireSpec::LogVar, Kind)
|
||||
WALK_NESTED_ENUM(ProcedureStmt, Kind) // R1506
|
||||
WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410
|
||||
#undef WALK_NESTED_ENUM
|
||||
|
||||
void Done() const { CHECK(indent_ == 0); }
|
||||
@@ -2020,8 +2020,8 @@ private:
|
||||
void Put(const std::string &);
|
||||
void PutKeywordLetter(char);
|
||||
void PutQuoted(const std::string &);
|
||||
void PutEnum(int, const char *);
|
||||
void Word(const char *);
|
||||
void Word(const std::string &);
|
||||
void Indent() { indent_ += indentationAmount_; }
|
||||
void Outdent() {
|
||||
CHECK(indent_ >= indentationAmount_);
|
||||
@@ -2144,27 +2144,16 @@ void UnparseVisitor::PutQuoted(const std::string &str) {
|
||||
Put('"');
|
||||
}
|
||||
|
||||
void UnparseVisitor::PutEnum(int n, const char *enumNames) {
|
||||
const char *p{enumNames};
|
||||
for (; n > 0; --n, ++p) {
|
||||
for (; *p && *p != ','; ++p) {
|
||||
}
|
||||
}
|
||||
while (*p == ' ') {
|
||||
++p;
|
||||
}
|
||||
CHECK(*p != '\0');
|
||||
for (; *p && *p != ' ' && *p != ','; ++p) {
|
||||
PutKeywordLetter(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void UnparseVisitor::Word(const char *str) {
|
||||
for (; *str != '\0'; ++str) {
|
||||
PutKeywordLetter(*str);
|
||||
}
|
||||
}
|
||||
|
||||
void UnparseVisitor::Word(const std::string &str) {
|
||||
Word(str.c_str());
|
||||
}
|
||||
|
||||
void Unparse(std::ostream &out, const Program &program, Encoding encoding,
|
||||
bool capitalizeKeywords) {
|
||||
UnparseVisitor visitor{out, 1, encoding, capitalizeKeywords};
|
||||
|
||||
@@ -7,38 +7,6 @@ namespace semantics {
|
||||
|
||||
constexpr static size_t toInt(Attr attr) { return static_cast<size_t>(attr); }
|
||||
|
||||
static const char *attrToString[] = {
|
||||
[toInt(Attr::ABSTRACT)] = "ABSTRACT",
|
||||
[toInt(Attr::ALLOCATABLE)] = "ALLOCATABLE",
|
||||
[toInt(Attr::ASYNCHRONOUS)] = "ASYNCHRONOUS",
|
||||
[toInt(Attr::BIND_C)] = "BIND_C",
|
||||
[toInt(Attr::CONTIGUOUS)] = "CONTIGUOUS",
|
||||
[toInt(Attr::DEFERRED)] = "DEFERRED",
|
||||
[toInt(Attr::ELEMENTAL)] = "ELEMENTAL",
|
||||
[toInt(Attr::EXTERNAL)] = "EXTERNAL",
|
||||
[toInt(Attr::IMPURE)] = "IMPURE",
|
||||
[toInt(Attr::INTENT_IN)] = "INTENT_IN",
|
||||
[toInt(Attr::INTENT_OUT)] = "INTENT_OUT",
|
||||
[toInt(Attr::INTRINSIC)] = "INTRINSIC",
|
||||
[toInt(Attr::MODULE)] = "MODULE",
|
||||
[toInt(Attr::NON_OVERRIDABLE)] = "NON_OVERRIDABLE",
|
||||
[toInt(Attr::NON_RECURSIVE)] = "NON_RECURSIVE",
|
||||
[toInt(Attr::NOPASS)] = "NOPASS",
|
||||
[toInt(Attr::OPTIONAL)] = "OPTIONAL",
|
||||
[toInt(Attr::PARAMETER)] = "PARAMETER",
|
||||
[toInt(Attr::PASS)] = "PASS",
|
||||
[toInt(Attr::POINTER)] = "POINTER",
|
||||
[toInt(Attr::PRIVATE)] = "PRIVATE",
|
||||
[toInt(Attr::PROTECTED)] = "PROTECTED",
|
||||
[toInt(Attr::PUBLIC)] = "PUBLIC",
|
||||
[toInt(Attr::PURE)] = "PURE",
|
||||
[toInt(Attr::RECURSIVE)] = "RECURSIVE",
|
||||
[toInt(Attr::SAVE)] = "SAVE",
|
||||
[toInt(Attr::TARGET)] = "TARGET",
|
||||
[toInt(Attr::VALUE)] = "VALUE",
|
||||
[toInt(Attr::VOLATILE)] = "VOLATILE",
|
||||
};
|
||||
|
||||
const Attrs Attrs::EMPTY;
|
||||
|
||||
Attrs::Attrs(std::initializer_list<Attr> attrs) {
|
||||
@@ -74,7 +42,7 @@ void Attrs::CheckValid(const Attrs &allowed) const {
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, Attr attr) {
|
||||
return o << attrToString[toInt(attr)];
|
||||
return o << EnumToString(attr);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const Attrs &attrs) {
|
||||
@@ -84,7 +52,7 @@ std::ostream &operator<<(std::ostream &o, const Attrs &attrs) {
|
||||
if (n++) {
|
||||
o << ", ";
|
||||
}
|
||||
o << attrToString[i];
|
||||
o << EnumToString(static_cast<Attr>(i));
|
||||
}
|
||||
}
|
||||
return o;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef FORTRAN_ATTR_H_
|
||||
#define FORTRAN_ATTR_H_
|
||||
|
||||
#include "../parser/idioms.h"
|
||||
#include <cinttypes>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@@ -8,38 +9,13 @@
|
||||
namespace Fortran {
|
||||
namespace semantics {
|
||||
|
||||
|
||||
// All available attributes.
|
||||
enum class Attr {
|
||||
ABSTRACT,
|
||||
ALLOCATABLE,
|
||||
ASYNCHRONOUS,
|
||||
BIND_C,
|
||||
CONTIGUOUS,
|
||||
DEFERRED,
|
||||
ELEMENTAL,
|
||||
EXTERNAL,
|
||||
IMPURE,
|
||||
INTENT_IN,
|
||||
INTENT_OUT,
|
||||
INTRINSIC,
|
||||
MODULE,
|
||||
NON_OVERRIDABLE,
|
||||
NON_RECURSIVE,
|
||||
NOPASS,
|
||||
OPTIONAL,
|
||||
PARAMETER,
|
||||
PASS,
|
||||
POINTER,
|
||||
PRIVATE,
|
||||
PROTECTED,
|
||||
PUBLIC,
|
||||
PURE,
|
||||
RECURSIVE,
|
||||
SAVE,
|
||||
TARGET,
|
||||
VALUE,
|
||||
VOLATILE,
|
||||
};
|
||||
ENUM_CLASS(Attr, ABSTRACT, ALLOCATABLE, ASYNCHRONOUS, BIND_C, CONTIGUOUS,
|
||||
DEFERRED, ELEMENTAL, EXTERNAL, IMPURE, INTENT_IN, INTENT_OUT, INTRINSIC,
|
||||
MODULE, NON_OVERRIDABLE, NON_RECURSIVE, NOPASS, OPTIONAL, PARAMETER, PASS,
|
||||
POINTER, PRIVATE, PROTECTED, PUBLIC, PURE, RECURSIVE, SAVE, TARGET, VALUE,
|
||||
VOLATILE)
|
||||
|
||||
// Set of attributes
|
||||
class Attrs {
|
||||
|
||||
Reference in New Issue
Block a user