[flang] More cleaning

Original-commit: flang-compiler/f18@8227229f62
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-08-14 15:11:53 -07:00
parent d986a35a5c
commit 5566d70ef2
6 changed files with 113 additions and 126 deletions

View File

@ -34,14 +34,6 @@ namespace Fortran::evaluate {
template<typename A> class Expr;
// An expression whose result is within one particular type category and
// of any supported kind.
using SomeKindIntegerExpr = Expr<SomeKind<TypeCategory::Integer>>;
using SomeKindRealExpr = Expr<SomeKind<TypeCategory::Real>>;
using SomeKindComplexExpr = Expr<SomeKind<TypeCategory::Complex>>;
using SomeKindCharacterExpr = Expr<SomeKind<TypeCategory::Character>>;
using SomeKindLogicalExpr = Expr<SomeKind<TypeCategory::Logical>>;
// Helper base classes for packaging subexpressions.
template<typename CRTP, typename RESULT, typename A = RESULT> class Unary {
public:
@ -96,16 +88,14 @@ public:
using Result = Type<TypeCategory::Integer, KIND>;
using FoldableTrait = std::true_type;
struct ConvertInteger
: public Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>> {
using Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>>::Unary;
struct ConvertInteger : public Unary<ConvertInteger, Result, SomeInteger> {
using Unary<ConvertInteger, Result, SomeInteger>::Unary;
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const SomeKindScalar<TypeCategory::Integer> &);
};
struct ConvertReal
: public Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>> {
using Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>>::Unary;
struct ConvertReal : public Unary<ConvertReal, Result, SomeReal> {
using Unary<ConvertReal, Result, SomeReal>::Unary;
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const SomeKindScalar<TypeCategory::Real> &);
};
@ -166,22 +156,22 @@ public:
Expr(std::int64_t n) : u_{Scalar<Result>{n}} {}
Expr(std::uint64_t n) : u_{Scalar<Result>{n}} {}
Expr(int n) : u_{Scalar<Result>{n}} {}
Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {}
Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {}
Expr(const Expr<SomeInteger> &x) : u_{ConvertInteger{x}} {}
Expr(Expr<SomeInteger> &&x) : u_{ConvertInteger{std::move(x)}} {}
template<int K>
Expr(const Expr<Type<TypeCategory::Integer, K>> &x)
: u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
: u_{ConvertInteger{Expr<SomeInteger>{x}}} {}
template<int K>
Expr(Expr<Type<TypeCategory::Integer, K>> &&x)
: u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {}
Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {}
Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {}
: u_{ConvertInteger{Expr<SomeInteger>{std::move(x)}}} {}
Expr(const Expr<SomeReal> &x) : u_{ConvertReal{x}} {}
Expr(Expr<SomeReal> &&x) : u_{ConvertReal{std::move(x)}} {}
template<int K>
Expr(const Expr<Type<TypeCategory::Real, K>> &x)
: u_{ConvertReal{SomeKindRealExpr{x}}} {}
: u_{ConvertReal{Expr<SomeReal>{x}}} {}
template<int K>
Expr(Expr<Type<TypeCategory::Real, K>> &&x)
: u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
: u_{ConvertReal{Expr<SomeReal>{std::move(x)}}} {}
template<typename A> Expr(const A &x) : u_{x} {}
template<typename A>
Expr(std::enable_if_t<!std::is_reference_v<A> &&
@ -210,15 +200,13 @@ public:
// N.B. Real->Complex and Complex->Real conversions are done with CMPLX
// and part access operations (resp.). Conversions between kinds of
// Complex are done via decomposition to Real and reconstruction.
struct ConvertInteger
: public Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>> {
using Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>>::Unary;
struct ConvertInteger : public Unary<ConvertInteger, Result, SomeInteger> {
using Unary<ConvertInteger, Result, SomeInteger>::Unary;
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const SomeKindScalar<TypeCategory::Integer> &);
};
struct ConvertReal
: public Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>> {
using Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>>::Unary;
struct ConvertReal : public Unary<ConvertReal, Result, SomeReal> {
using Unary<ConvertReal, Result, SomeReal>::Unary;
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const SomeKindScalar<TypeCategory::Real> &);
};
@ -261,10 +249,8 @@ public:
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const Scalar<Result> &, const Scalar<Result> &);
};
struct IntPower
: public Binary<IntPower, Result, Result, SomeKind<TypeCategory::Integer>> {
using Binary<IntPower, Result, Result,
SomeKind<TypeCategory::Integer>>::Binary;
struct IntPower : public Binary<IntPower, Result, Result, SomeInteger> {
using Binary<IntPower, Result, Result, SomeInteger>::Binary;
static std::optional<Scalar<Result>> FoldScalar(FoldingContext &,
const Scalar<Result> &, const SomeKindScalar<TypeCategory::Integer> &);
};
@ -294,22 +280,22 @@ public:
CLASS_BOILERPLATE(Expr)
Expr(const Scalar<Result> &x) : u_{x} {}
Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {}
Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {}
Expr(const Expr<SomeInteger> &x) : u_{ConvertInteger{x}} {}
Expr(Expr<SomeInteger> &&x) : u_{ConvertInteger{std::move(x)}} {}
template<int K>
Expr(const Expr<Type<TypeCategory::Integer, K>> &x)
: u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
: u_{ConvertInteger{Expr<SomeInteger>{x}}} {}
template<int K>
Expr(Expr<Type<TypeCategory::Integer, K>> &&x)
: u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {}
Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {}
Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {}
: u_{ConvertInteger{Expr<SomeInteger>{std::move(x)}}} {}
Expr(const Expr<SomeReal> &x) : u_{ConvertReal{x}} {}
Expr(Expr<SomeReal> &&x) : u_{ConvertReal{std::move(x)}} {}
template<int K>
Expr(const Expr<Type<TypeCategory::Real, K>> &x)
: u_{ConvertReal{SomeKindRealExpr{x}}} {}
: u_{ConvertReal{Expr<SomeReal>{x}}} {}
template<int K>
Expr(Expr<Type<TypeCategory::Real, K>> &&x)
: u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
: u_{ConvertReal{Expr<SomeReal>{std::move(x)}}} {}
template<typename A> Expr(const A &x) : u_{x} {}
template<typename A>
Expr(std::enable_if_t<!std::is_reference_v<A>, A> &&x) : u_{std::move(x)} {}
@ -372,10 +358,8 @@ public:
static std::optional<Scalar<Result>> FoldScalar(
FoldingContext &, const Scalar<Result> &, const Scalar<Result> &);
};
struct IntPower
: public Binary<IntPower, Result, Result, SomeKind<TypeCategory::Integer>> {
using Binary<IntPower, Result, Result,
SomeKind<TypeCategory::Integer>>::Binary;
struct IntPower : public Binary<IntPower, Result, Result, SomeInteger> {
using Binary<IntPower, Result, Result, SomeInteger>::Binary;
static std::optional<Scalar<Result>> FoldScalar(FoldingContext &,
const Scalar<Result> &, const SomeKindScalar<TypeCategory::Integer> &);
};
@ -595,11 +579,11 @@ public:
typename KindsVariant<CAT, KindExpr>::type u;
};
extern template class Expr<SomeKind<TypeCategory::Integer>>;
extern template class Expr<SomeKind<TypeCategory::Real>>;
extern template class Expr<SomeKind<TypeCategory::Complex>>;
extern template class Expr<SomeKind<TypeCategory::Character>>;
extern template class Expr<SomeKind<TypeCategory::Logical>>;
extern template class Expr<SomeInteger>;
extern template class Expr<SomeReal>;
extern template class Expr<SomeComplex>;
extern template class Expr<SomeCharacter>;
extern template class Expr<SomeLogical>;
// BOZ literal constants need to be wide enough to hold an integer or real
// value of any supported kind. They also need to be distinguishable from
@ -629,8 +613,8 @@ public:
std::optional<Scalar<Result>> Fold(FoldingContext &);
int Rank() const { return 1; } // TODO
std::variant<SomeKindIntegerExpr, SomeKindRealExpr, SomeKindComplexExpr,
SomeKindCharacterExpr, SomeKindLogicalExpr, BOZLiteralConstant>
std::variant<Expr<SomeInteger>, Expr<SomeReal>, Expr<SomeComplex>,
Expr<SomeCharacter>, Expr<SomeLogical>, BOZLiteralConstant>
u;
};

View File

@ -20,53 +20,51 @@ using namespace Fortran::parser::literals;
namespace Fortran::evaluate {
SomeKindRealExpr ConvertToTypeOf(
const SomeKindRealExpr &to, const SomeKindIntegerExpr &from) {
Expr<SomeReal> ConvertToTypeOf(
const Expr<SomeReal> &to, const Expr<SomeInteger> &from) {
return std::visit(
[&](const auto &rk) { return SomeKindRealExpr{decltype(rk){to}}; }, to.u);
[&](const auto &rk) { return Expr<SomeReal>{decltype(rk){to}}; }, to.u);
}
SomeKindRealExpr ConvertToTypeOf(
const SomeKindRealExpr &to, const SomeKindRealExpr &from) {
Expr<SomeReal> ConvertToTypeOf(
const Expr<SomeReal> &to, const Expr<SomeReal> &from) {
return std::visit(
[&](const auto &rk) { return SomeKindRealExpr{decltype(rk){to}}; }, to.u);
[&](const auto &rk) { return Expr<SomeReal>{decltype(rk){to}}; }, to.u);
}
std::optional<std::pair<SomeKindRealExpr, SomeKindRealExpr>>
ConvertRealOperands(
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
parser::ContextualMessages &messages, GenericExpr &&x, GenericExpr &&y) {
return std::visit(
common::visitors{
[&](SomeKindIntegerExpr &&ix, SomeKindIntegerExpr &&iy) {
// Can happen in a CMPLX() constructor. Per F'2018, both integer
// operands are converted to default REAL.
return std::optional{std::make_pair(
SomeKindRealExpr{Expr<DefaultReal>{std::move(ix)}},
SomeKindRealExpr{Expr<DefaultReal>{std::move(iy)}})};
},
[&](SomeKindIntegerExpr &&ix, SomeKindRealExpr &&ry) {
common::visitors{[&](Expr<SomeInteger> &&ix, Expr<SomeInteger> &&iy) {
// Can happen in a CMPLX() constructor. Per F'2018,
// both integer operands are converted to default REAL.
return std::optional{std::make_pair(
Expr<SomeReal>{Expr<DefaultReal>{std::move(ix)}},
Expr<SomeReal>{Expr<DefaultReal>{std::move(iy)}})};
},
[&](Expr<SomeInteger> &&ix, Expr<SomeReal> &&ry) {
auto rx{ConvertToTypeOf(ry, std::move(ix))};
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
},
[&](SomeKindRealExpr &&rx, SomeKindIntegerExpr &&iy) {
[&](Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
auto ry{ConvertToTypeOf(rx, std::move(iy))};
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
},
[&](SomeKindRealExpr &&rx, SomeKindRealExpr &&ry) {
[&](Expr<SomeReal> &&rx, Expr<SomeReal> &&ry) {
ConvertToSameKind(rx, ry);
return std::optional{std::make_pair(std::move(rx), std::move(ry))};
},
[&](const auto &, const auto &)
-> std::optional<std::pair<SomeKindRealExpr, SomeKindRealExpr>> {
-> std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> {
messages.Say("operands must be INTEGER or REAL"_err_en_US);
return std::nullopt;
}},
std::move(x.u), std::move(y.u));
}
std::optional<std::pair<SomeKindRealExpr, SomeKindRealExpr>>
ConvertRealOperands(parser::ContextualMessages &messages,
std::optional<GenericExpr> &&x, std::optional<GenericExpr> &&y) {
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>> ConvertRealOperands(
parser::ContextualMessages &messages, std::optional<GenericExpr> &&x,
std::optional<GenericExpr> &&y) {
if (x.has_value() && y.has_value()) {
return ConvertRealOperands(messages, std::move(*x), std::move(*y));
}

View File

@ -24,15 +24,15 @@
namespace Fortran::evaluate {
// Convert the second argument to the same type and kind of the first.
SomeKindRealExpr ConvertToTypeOf(
const SomeKindRealExpr &to, const SomeKindIntegerExpr &from);
SomeKindRealExpr ConvertToTypeOf(
const SomeKindRealExpr &to, const SomeKindRealExpr &from);
Expr<SomeReal> ConvertToTypeOf(
const Expr<SomeReal> &to, const Expr<SomeInteger> &from);
Expr<SomeReal> ConvertToTypeOf(
const Expr<SomeReal> &to, const Expr<SomeReal> &from);
// Ensure that both operands of an intrinsic REAL operation or CMPLX()
// are INTEGER or REAL, and convert them as necessary to the same REAL type.
using ConvertRealOperandsResult =
std::optional<std::pair<SomeKindRealExpr, SomeKindRealExpr>>;
std::optional<std::pair<Expr<SomeReal>, Expr<SomeReal>>>;
ConvertRealOperandsResult ConvertRealOperands(
parser::ContextualMessages &, GenericExpr &&, GenericExpr &&);

View File

@ -107,6 +107,7 @@ struct Type<TypeCategory::Logical, KIND>
// Type functions
template<typename T> using Scalar = typename std::decay_t<T>::Scalar;
template<TypeCategory C, typename T>
using SameKind = Type<C, std::decay_t<T>::kind>;
@ -201,13 +202,6 @@ template<TypeCategory CAT> struct SomeKindScalar {
typename KindsVariant<CAT, KindScalar>::type u;
};
struct GenericScalar;
// Represents a completely generic type.
struct SomeType {
using Scalar = GenericScalar;
};
// Holds a scalar constant of any intrinsic category and size.
struct GenericScalar {
CLASS_BOILERPLATE(GenericScalar)
@ -239,5 +233,16 @@ template<TypeCategory CAT> struct SomeKind {
using Scalar = SomeKindScalar<CAT>;
};
using SomeInteger = SomeKind<TypeCategory::Integer>;
using SomeReal = SomeKind<TypeCategory::Real>;
using SomeComplex = SomeKind<TypeCategory::Complex>;
using SomeCharacter = SomeKind<TypeCategory::Character>;
using SomeLogical = SomeKind<TypeCategory::Logical>;
// Represents a completely generic type.
struct SomeType {
using Scalar = GenericScalar;
};
} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_TYPE_H_

View File

@ -24,6 +24,9 @@ using namespace Fortran::parser::literals;
namespace Fortran::semantics {
using common::TypeCategory;
using evaluate::Expr;
using evaluate::GenericExpr;
using evaluate::Type;
// AnalyzeHelper is a local template function that keeps the API
// member function ExpressionAnalyzer::Analyze from having to be a
@ -77,31 +80,29 @@ MaybeExpr AnalyzeHelper(
return result;
}
// TODO: Return
// std::optional<evaluate::Expr<evaluate::SomeKind<TypeCategory::Integer>>> here
// instead
// TODO: Return std::optional<Expr<SomeInteger>> here instead
template<typename A>
MaybeExpr AnalyzeHelper(
ExpressionAnalyzer &ea, const parser::Integer<A> &tree) {
MaybeExpr result{AnalyzeHelper(ea, tree.thing)};
if (result.has_value() &&
!std::holds_alternative<evaluate::SomeKindIntegerExpr>(result->u)) {
!std::holds_alternative<Expr<evaluate::SomeInteger>>(result->u)) {
ea.context().messages.Say("must be integer"_err_en_US);
return std::nullopt;
}
return result;
}
static std::optional<evaluate::SomeKindCharacterExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeCharacter>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::CharLiteralConstant &x) {
auto kind{ea.Analyze(std::get<std::optional<parser::KindParam>>(x.t),
ExpressionAnalyzer::KindParam{1})};
switch (kind) {
#define CASE(k) \
case k: { \
using Ty = evaluate::Type<TypeCategory::Character, k>; \
return {evaluate::SomeKindCharacterExpr{ \
evaluate::Expr<Ty>{std::get<std::string>(x.t)}}}; \
using Ty = Type<TypeCategory::Character, k>; \
return { \
Expr<evaluate::SomeCharacter>{Expr<Ty>{std::get<std::string>(x.t)}}}; \
}
FOR_EACH_CHARACTER_KIND(CASE, )
#undef CASE
@ -114,7 +115,7 @@ static std::optional<evaluate::SomeKindCharacterExpr> AnalyzeLiteral(
template<typename A> MaybeExpr PackageGeneric(std::optional<A> &&x) {
std::function<GenericExpr(A &&)> f{
[](A &&y) -> GenericExpr { return {std::move(y)}; }};
[](A &&y) { return GenericExpr{std::move(y)}; }};
return common::MapOptional(f, std::move(x));
}
@ -131,11 +132,11 @@ MaybeExpr AnalyzeHelper(
}
// TODO: ensure that any kind parameter is 1
std::string str{std::get<parser::CharLiteralConstant>(x.t).GetString()};
std::optional<evaluate::Expr<evaluate::SubscriptInteger>> lb, ub;
std::optional<Expr<evaluate::SubscriptInteger>> lb, ub;
if (lbTree.has_value()) {
if (MaybeExpr lbExpr{AnalyzeHelper(ea, *lbTree)}) {
if (auto *ie{std::get_if<evaluate::SomeKindIntegerExpr>(&lbExpr->u)}) {
lb = evaluate::Expr<evaluate::SubscriptInteger>{std::move(*ie)};
if (auto *ie{std::get_if<Expr<evaluate::SomeInteger>>(&lbExpr->u)}) {
lb = Expr<evaluate::SubscriptInteger>{std::move(*ie)};
} else {
ea.context().messages.Say(
"scalar integer expression required for substring lower bound"_err_en_US);
@ -144,8 +145,8 @@ MaybeExpr AnalyzeHelper(
}
if (ubTree.has_value()) {
if (MaybeExpr ubExpr{AnalyzeHelper(ea, *ubTree)}) {
if (auto *ie{std::get_if<evaluate::SomeKindIntegerExpr>(&ubExpr->u)}) {
ub = evaluate::Expr<evaluate::SubscriptInteger>{std::move(*ie)};
if (auto *ie{std::get_if<Expr<evaluate::SomeInteger>>(&ubExpr->u)}) {
ub = Expr<evaluate::SubscriptInteger>{std::move(*ie)};
} else {
ea.context().messages.Say(
"scalar integer expression required for substring upper bound"_err_en_US);
@ -157,14 +158,14 @@ MaybeExpr AnalyzeHelper(
}
evaluate::Substring substring{std::move(str), std::move(lb), std::move(ub)};
evaluate::CopyableIndirection<evaluate::Substring> ind{std::move(substring)};
evaluate::Expr<evaluate::DefaultCharacter> chExpr{std::move(ind)};
Expr<evaluate::DefaultCharacter> chExpr{std::move(ind)};
chExpr.Fold(ea.context());
return {GenericExpr{evaluate::SomeKindCharacterExpr{std::move(chExpr)}}};
return {GenericExpr{Expr<evaluate::SomeCharacter>{std::move(chExpr)}}};
}
// Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
template<typename PARSED>
std::optional<evaluate::SomeKindIntegerExpr> IntLiteralConstant(
std::optional<Expr<evaluate::SomeInteger>> IntLiteralConstant(
ExpressionAnalyzer &ea, const PARSED &x) {
auto kind{ea.Analyze(std::get<std::optional<parser::KindParam>>(x.t),
ea.defaultIntegerKind())};
@ -172,8 +173,8 @@ std::optional<evaluate::SomeKindIntegerExpr> IntLiteralConstant(
switch (kind) {
#define CASE(k) \
case k: { \
using Ty = evaluate::Type<TypeCategory::Integer, k>; \
return {evaluate::ToSomeKindExpr(evaluate::Expr<Ty>{value})}; \
using Ty = Type<TypeCategory::Integer, k>; \
return {evaluate::ToSomeKindExpr(Expr<Ty>{value})}; \
}
FOR_EACH_INTEGER_KIND(CASE, )
#undef CASE
@ -184,12 +185,12 @@ std::optional<evaluate::SomeKindIntegerExpr> IntLiteralConstant(
}
}
static std::optional<evaluate::SomeKindIntegerExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeInteger>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::IntLiteralConstant &x) {
return IntLiteralConstant(ea, x);
}
static std::optional<evaluate::SomeKindIntegerExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeInteger>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::SignedIntLiteralConstant &x) {
return IntLiteralConstant(ea, x);
}
@ -220,10 +221,10 @@ static std::optional<evaluate::BOZLiteralConstant> AnalyzeLiteral(
}
template<int KIND>
std::optional<evaluate::SomeKindRealExpr> ReadRealLiteral(
std::optional<Expr<evaluate::SomeReal>> ReadRealLiteral(
parser::CharBlock source, evaluate::FoldingContext &context) {
const char *p{source.begin()};
using RealType = evaluate::Type<TypeCategory::Real, KIND>;
using RealType = Type<TypeCategory::Real, KIND>;
auto valWithFlags{evaluate::Scalar<RealType>::Read(p, context.rounding)};
CHECK(p == source.end());
evaluate::RealFlagWarnings(
@ -232,10 +233,10 @@ std::optional<evaluate::SomeKindRealExpr> ReadRealLiteral(
if (context.flushDenormalsToZero) {
value = value.FlushDenormalToZero();
}
return {evaluate::ToSomeKindExpr(evaluate::Expr<RealType>{value})};
return {evaluate::ToSomeKindExpr(Expr<RealType>{value})};
}
static std::optional<evaluate::SomeKindRealExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeReal>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::RealLiteralConstant &x) {
// Use a local message context around the real literal.
parser::ContextualMessages ctxMsgs{x.real.source, ea.context().messages};
@ -269,7 +270,7 @@ static std::optional<evaluate::SomeKindRealExpr> AnalyzeLiteral(
}
}
static std::optional<evaluate::SomeKindRealExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeReal>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::SignedRealLiteralConstant &x) {
auto result{AnalyzeLiteral(ea, std::get<parser::RealLiteralConstant>(x.t))};
if (result.has_value()) {
@ -321,19 +322,19 @@ MaybeExpr AnalyzeHelper(ExpressionAnalyzer &ea, const parser::ComplexPart &x) {
// to default REAL and the result is default COMPLEX. Otherwise, the
// kind of the result is the kind of largest REAL component, and the other
// component is converted if necessary its type.
static std::optional<evaluate::SomeKindComplexExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeComplex>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::ComplexLiteralConstant &z) {
const parser::ComplexPart &re{std::get<0>(z.t)}, &im{std::get<1>(z.t)};
return ea.ConstructComplex(AnalyzeHelper(ea, re), AnalyzeHelper(ea, im));
}
static std::optional<evaluate::SomeKindCharacterExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeCharacter>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::HollerithLiteralConstant &x) {
evaluate::Expr<evaluate::DefaultCharacter> expr{x.v};
return {evaluate::SomeKindCharacterExpr{expr}};
Expr<evaluate::DefaultCharacter> expr{x.v};
return {Expr<evaluate::SomeCharacter>{expr}};
}
static std::optional<evaluate::SomeKindLogicalExpr> AnalyzeLiteral(
static std::optional<Expr<evaluate::SomeLogical>> AnalyzeLiteral(
ExpressionAnalyzer &ea, const parser::LogicalLiteralConstant &x) {
auto kind{ea.Analyze(std::get<std::optional<parser::KindParam>>(x.t),
ea.defaultLogicalKind())};
@ -341,8 +342,8 @@ static std::optional<evaluate::SomeKindLogicalExpr> AnalyzeLiteral(
switch (kind) {
#define CASE(k) \
case k: { \
using Ty = evaluate::Type<TypeCategory::Logical, k>; \
return {evaluate::SomeKindLogicalExpr{evaluate::Expr<Ty>{value}}}; \
using Ty = Type<TypeCategory::Logical, k>; \
return {Expr<evaluate::SomeLogical>{Expr<Ty>{value}}}; \
}
FOR_EACH_LOGICAL_KIND(CASE, )
#undef CASE
@ -596,8 +597,8 @@ ExpressionAnalyzer::KindParam ExpressionAnalyzer::Analyze(
kindParam->u);
}
std::optional<evaluate::SomeKindComplexExpr>
ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) {
std::optional<Expr<evaluate::SomeComplex>> ExpressionAnalyzer::ConstructComplex(
MaybeExpr &&real, MaybeExpr &&imaginary) {
// TODO: pmk abstract further, this will be a common pattern
auto partial{[&](GenericExpr &&x, GenericExpr &&y) {
return evaluate::ConvertRealOperands(
@ -609,10 +610,10 @@ ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) {
auto converted{common::MapOptional(f, std::move(real), std::move(imaginary))};
if (auto joined{common::JoinOptionals(std::move(converted))}) {
return {std::visit(
[](auto &&rx, auto &&ix) -> evaluate::SomeKindComplexExpr {
[](auto &&rx, auto &&ix) -> Expr<evaluate::SomeComplex> {
using realType = evaluate::ResultType<decltype(rx)>;
using zType = evaluate::SameKind<TypeCategory::Complex, realType>;
using zExpr = evaluate::Expr<zType>;
using zExpr = Expr<zType>;
return {zExpr{typename zExpr::CMPLX{std::move(rx), std::move(ix)}}};
},
std::move(joined->first.u), std::move(joined->second.u))};

View File

@ -23,8 +23,7 @@
namespace Fortran::semantics {
using evaluate::GenericExpr;
using MaybeExpr = std::optional<GenericExpr>;
using MaybeExpr = std::optional<evaluate::GenericExpr>;
class ExpressionAnalyzer {
public:
@ -44,7 +43,7 @@ public:
KindParam Analyze(const std::optional<parser::KindParam> &,
KindParam defaultKind, KindParam kanjiKind = -1 /* not allowed here */);
std::optional<evaluate::SomeKindComplexExpr> ConstructComplex(
std::optional<evaluate::Expr<evaluate::SomeComplex>> ConstructComplex(
MaybeExpr &&real, MaybeExpr &&imaginary);
private: