forked from OSchip/llvm-project
[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:
parent
d986a35a5c
commit
5566d70ef2
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 &&);
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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))};
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue