@@ -898,12 +898,24 @@ Expr<RESULT> MapOperation(FoldingContext &context,
898
898
context, std::move (result), AsConstantExtents (context, shape));
899
899
}
900
900
901
+ template <typename RESULT, typename A>
902
+ ArrayConstructor<RESULT> ArrayConstructorFromMold (
903
+ const A &prototype, std::optional<Expr<SubscriptInteger>> &&length) {
904
+ if constexpr (RESULT::category == TypeCategory::Character) {
905
+ return ArrayConstructor<RESULT>{
906
+ std::move (length.value ()), ArrayConstructorValues<RESULT>{}};
907
+ } else {
908
+ return ArrayConstructor<RESULT>{prototype};
909
+ }
910
+ }
911
+
901
912
// array * array case
902
913
template <typename RESULT, typename LEFT, typename RIGHT>
903
914
Expr<RESULT> MapOperation (FoldingContext &context,
904
915
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
905
- const Shape &shape, Expr<LEFT> &&leftValues, Expr<RIGHT> &&rightValues) {
906
- ArrayConstructor<RESULT> result{leftValues};
916
+ const Shape &shape, std::optional<Expr<SubscriptInteger>> &&length,
917
+ Expr<LEFT> &&leftValues, Expr<RIGHT> &&rightValues) {
918
+ auto result{ArrayConstructorFromMold<RESULT>(leftValues, std::move (length))};
907
919
auto &leftArrConst{std::get<ArrayConstructor<LEFT>>(leftValues.u )};
908
920
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
909
921
std::visit (
@@ -942,9 +954,9 @@ Expr<RESULT> MapOperation(FoldingContext &context,
942
954
template <typename RESULT, typename LEFT, typename RIGHT>
943
955
Expr<RESULT> MapOperation (FoldingContext &context,
944
956
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
945
- const Shape &shape, Expr<LEFT> &&leftValues ,
946
- const Expr<RIGHT> &rightScalar) {
947
- ArrayConstructor<RESULT> result{leftValues};
957
+ const Shape &shape, std::optional< Expr<SubscriptInteger>> &&length ,
958
+ Expr<LEFT> &&leftValues, const Expr<RIGHT> &rightScalar) {
959
+ auto result{ArrayConstructorFromMold<RESULT>( leftValues, std::move (length)) };
948
960
auto &leftArrConst{std::get<ArrayConstructor<LEFT>>(leftValues.u )};
949
961
for (auto &leftValue : leftArrConst) {
950
962
auto &leftScalar{std::get<Expr<LEFT>>(leftValue.u )};
@@ -959,9 +971,9 @@ Expr<RESULT> MapOperation(FoldingContext &context,
959
971
template <typename RESULT, typename LEFT, typename RIGHT>
960
972
Expr<RESULT> MapOperation (FoldingContext &context,
961
973
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
962
- const Shape &shape, const Expr<LEFT> &leftScalar ,
963
- Expr<RIGHT> &&rightValues) {
964
- ArrayConstructor<RESULT> result{leftScalar};
974
+ const Shape &shape, std::optional< Expr<SubscriptInteger>> &&length ,
975
+ const Expr<LEFT> &leftScalar, Expr<RIGHT> &&rightValues) {
976
+ auto result{ArrayConstructorFromMold<RESULT>( leftScalar, std::move (length)) };
965
977
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
966
978
std::visit (
967
979
[&](auto &&kindExpr) {
@@ -987,6 +999,15 @@ Expr<RESULT> MapOperation(FoldingContext &context,
987
999
context, std::move (result), AsConstantExtents (context, shape));
988
1000
}
989
1001
1002
+ template <typename DERIVED, typename RESULT, typename LEFT, typename RIGHT>
1003
+ std::optional<Expr<SubscriptInteger>> ComputeResultLength (
1004
+ Operation<DERIVED, RESULT, LEFT, RIGHT> &operation) {
1005
+ if constexpr (RESULT::category == TypeCategory::Character) {
1006
+ return Expr<RESULT>{operation.derived ()}.LEN ();
1007
+ }
1008
+ return std::nullopt;
1009
+ }
1010
+
990
1011
// ApplyElementwise() recursively folds the operand expression(s) of an
991
1012
// operation, then attempts to apply the operation to the (corresponding)
992
1013
// scalar element(s) of those operands. Returns std::nullopt for scalars
@@ -1024,6 +1045,7 @@ auto ApplyElementwise(FoldingContext &context,
1024
1045
Operation<DERIVED, RESULT, LEFT, RIGHT> &operation,
1025
1046
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f)
1026
1047
-> std::optional<Expr<RESULT>> {
1048
+ auto resultLength{ComputeResultLength (operation)};
1027
1049
auto &leftExpr{operation.left ()};
1028
1050
leftExpr = Fold (context, std::move (leftExpr));
1029
1051
auto &rightExpr{operation.right ()};
@@ -1038,25 +1060,26 @@ auto ApplyElementwise(FoldingContext &context,
1038
1060
CheckConformanceFlags::EitherScalarExpandable)
1039
1061
.value_or (false /* fail if not known now to conform*/ )) {
1040
1062
return MapOperation (context, std::move (f), *leftShape,
1041
- std::move (*left), std::move (*right));
1063
+ std::move (resultLength), std::move (*left),
1064
+ std::move (*right));
1042
1065
} else {
1043
1066
return std::nullopt;
1044
1067
}
1045
1068
return MapOperation (context, std::move (f), *leftShape,
1046
- std::move (*left), std::move (*right));
1069
+ std::move (resultLength), std::move ( *left), std::move (*right));
1047
1070
}
1048
1071
}
1049
1072
} else if (IsExpandableScalar (rightExpr)) {
1050
- return MapOperation (
1051
- context, std::move (f), *leftShape , std::move (*left), rightExpr);
1073
+ return MapOperation (context, std::move (f), *leftShape,
1074
+ std::move (resultLength) , std::move (*left), rightExpr);
1052
1075
}
1053
1076
}
1054
1077
}
1055
1078
} else if (rightExpr.Rank () > 0 && IsExpandableScalar (leftExpr)) {
1056
1079
if (std::optional<Shape> shape{GetShape (context, rightExpr)}) {
1057
1080
if (auto right{AsFlatArrayConstructor (rightExpr)}) {
1058
- return MapOperation (
1059
- context, std::move (f), *shape , leftExpr, std::move (*right));
1081
+ return MapOperation (context, std::move (f), *shape,
1082
+ std::move (resultLength) , leftExpr, std::move (*right));
1060
1083
}
1061
1084
}
1062
1085
}
0 commit comments