[flang] Finish typeless casting

Original-commit: flang-compiler/f18@a4cfd1696a
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-09-04 14:20:48 -07:00
parent 5f43f78b82
commit 0b2d90bc00
2 changed files with 33 additions and 24 deletions

View File

@ -57,12 +57,15 @@ ConvertRealOperandsResult ConvertRealOperands(
std::move(x.u), std::move(y.u));
}
// A helper template for NumericOperation below.
template<TypeCategory CAT>
std::optional<Expr<SomeType>> Package(Expr<SomeKind<CAT>> &&catExpr) {
return {AsGenericExpr(std::move(catExpr))};
}
// TODO pmk next: write in terms of ConvertRealOperands?
// N.B. When a "typeless" BOZ literal constant appears as one (not both!) of
// the operands to a dyadic INTEGER or REAL operation, it assumes the type
// and kind of the other operand.
template<template<typename> class OPR>
std::optional<Expr<SomeType>> NumericOperation(
parser::ContextualMessages &messages, Expr<SomeType> &&x,
@ -90,9 +93,8 @@ std::optional<Expr<SomeType>> NumericOperation(
return Package(std::visit(
[&](auto &&ryk) -> Expr<SomeReal> {
using resultType = ResultType<decltype(ryk)>;
return AsCategoryExpr(AsExpr(
OPR<resultType>{ConvertToType<resultType>(std::move(ix)),
std::move(ryk)}));
return AsCategoryExpr(AsExpr(OPR<resultType>{
ConvertToType<resultType>(std::move(ix)), std::move(ryk)}));
},
std::move(ry.u)));
},
@ -100,27 +102,19 @@ std::optional<Expr<SomeType>> NumericOperation(
return Package(PromoteAndCombine<OPR, TypeCategory::Complex>(
std::move(zx), std::move(zy)));
},
[&](BOZLiteralConstant &&bx, Expr<SomeInteger> &&iy) {
return NumericOperation<OPR>(messages, ConvertTo(iy, std::move(bx)), std::move(y));
},
[&](BOZLiteralConstant &&bx, Expr<SomeReal> &&ry) {
return NumericOperation<OPR>(messages, ConvertTo(ry, std::move(bx)), std::move(y));
},
[&](Expr<SomeInteger> &&ix, BOZLiteralConstant &&by) {
return NumericOperation<OPR>(messages, std::move(x), ConvertTo(ix, std::move(by)));
},
[&](Expr<SomeReal> &&rx, BOZLiteralConstant &&by) {
return NumericOperation<OPR>(messages, std::move(x), ConvertTo(rx, std::move(by)));
},
// TODO pmk mixed complex; Add/Sub different from Mult/Div
[](BOZLiteralConstant &&bx, Expr<SomeInteger> &&iy) {
return Package(std::visit(
[&](auto &&iyk) -> Expr<SomeInteger> {
using resultType = ResultType<decltype(iyk)>;
return AsCategoryExpr(AsExpr(OPR<resultType>{
AsExpr(BOZConstant<resultType>{std::move(bx)}),
std::move(iyk)}));
},
iy.u));
},
[](BOZLiteralConstant &&bx, Expr<SomeReal> &&ry) {
return Package(std::visit(
[&](auto &&ryk) -> Expr<SomeReal> {
using resultType = ResultType<decltype(ryk)>;
return AsCategoryExpr(AsExpr(OPR<resultType>{
AsExpr(BOZConstant<resultType>{std::move(bx)}),
std::move(ryk)}));
},
ry.u));
},
[&](auto &&, auto &&) {
messages.Say("non-numeric operands to numeric operation"_err_en_US);
return std::optional<Expr<SomeType>>{std::nullopt};

View File

@ -123,6 +123,13 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
}
}
template<typename TO>
Expr<TO> ConvertToType(BOZLiteralConstant &&x) {
// TODO: check rank == 0
static_assert(TO::isSpecificType);
return Expr<TO>{BOZConstant<TO>{std::move(x)}};
}
template<TypeCategory TC, int TK, TypeCategory FC>
Expr<Type<TC, TK>> ConvertTo(
const Expr<Type<TC, TK>> &, Expr<SomeKind<FC>> &&x) {
@ -162,6 +169,14 @@ Expr<SomeType> ConvertTo(const Expr<SomeType> &to, Expr<FT> &&from) {
to.u);
}
template<TypeCategory CAT>
Expr<SomeType> ConvertTo(const Expr<SomeKind<CAT>> &to, BOZLiteralConstant &&from) {
return AsGenericExpr(std::visit([&](const auto &tok) {
using Ty = ResultType<decltype(tok)>;
return AsCategoryExpr(ConvertToType<Ty>(std::move(from)));
}, to.u));
}
template<typename A, int N = 2> using SameExprs = std::array<Expr<A>, N>;
// Given a type category CAT, SameKindExprs<CAT, N> is a variant that