2019-01-28 23:38:17 +01:00
|
|
|
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
2018-06-20 20:55:10 +02:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#include "expression.h"
|
2018-08-09 01:30:58 +02:00
|
|
|
#include "common.h"
|
2018-07-25 22:46:13 +02:00
|
|
|
#include "int-power.h"
|
2018-08-20 18:29:08 +02:00
|
|
|
#include "tools.h"
|
2018-07-07 00:12:33 +02:00
|
|
|
#include "variable.h"
|
2018-06-20 20:55:10 +02:00
|
|
|
#include "../common/idioms.h"
|
2018-07-24 21:58:29 +02:00
|
|
|
#include "../parser/message.h"
|
2018-06-20 20:55:10 +02:00
|
|
|
#include <ostream>
|
2019-01-23 01:30:32 +01:00
|
|
|
#include <sstream>
|
2018-06-20 20:55:10 +02:00
|
|
|
#include <string>
|
2018-06-21 01:50:27 +02:00
|
|
|
#include <type_traits>
|
2018-06-20 20:55:10 +02:00
|
|
|
|
2018-06-22 23:51:15 +02:00
|
|
|
using namespace Fortran::parser::literals;
|
|
|
|
|
2018-06-20 20:55:10 +02:00
|
|
|
namespace Fortran::evaluate {
|
|
|
|
|
2018-11-06 00:02:37 +01:00
|
|
|
// AsFortran() formatting
|
2018-08-18 00:38:37 +02:00
|
|
|
|
|
|
|
template<typename D, typename R, typename... O>
|
2018-11-06 00:02:37 +01:00
|
|
|
std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const {
|
|
|
|
left().AsFortran(derived().Prefix(o));
|
2018-09-07 19:33:32 +02:00
|
|
|
if constexpr (operands > 1) {
|
2018-11-06 00:02:37 +01:00
|
|
|
right().AsFortran(derived().Infix(o));
|
2018-08-18 00:38:37 +02:00
|
|
|
}
|
2018-09-07 19:33:32 +02:00
|
|
|
return derived().Suffix(o);
|
2018-08-18 00:38:37 +02:00
|
|
|
}
|
|
|
|
|
2018-09-07 19:33:32 +02:00
|
|
|
template<typename TO, TypeCategory FROMCAT>
|
2018-11-06 00:02:37 +01:00
|
|
|
std::ostream &Convert<TO, FROMCAT>::AsFortran(std::ostream &o) const {
|
2018-09-07 19:33:32 +02:00
|
|
|
static_assert(TO::category == TypeCategory::Integer ||
|
|
|
|
TO::category == TypeCategory::Real ||
|
|
|
|
TO::category == TypeCategory::Logical || !"Convert<> to bad category!");
|
|
|
|
if constexpr (TO::category == TypeCategory::Integer) {
|
2018-11-14 23:35:10 +01:00
|
|
|
o << "int";
|
2018-09-07 19:33:32 +02:00
|
|
|
} else if constexpr (TO::category == TypeCategory::Real) {
|
2018-11-14 23:35:10 +01:00
|
|
|
o << "real";
|
2018-09-07 19:33:32 +02:00
|
|
|
} else if constexpr (TO::category == TypeCategory::Logical) {
|
2018-11-14 23:35:10 +01:00
|
|
|
o << "logical";
|
2018-09-07 19:33:32 +02:00
|
|
|
}
|
2018-11-14 23:35:10 +01:00
|
|
|
return this->left().AsFortran(o << '(') << ",kind=" << TO::kind << ')';
|
2018-09-07 19:33:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A> std::ostream &Relational<A>::Infix(std::ostream &o) const {
|
2018-11-14 23:35:10 +01:00
|
|
|
switch (opr) {
|
|
|
|
case RelationalOperator::LT: o << '<'; break;
|
|
|
|
case RelationalOperator::LE: o << "<="; break;
|
|
|
|
case RelationalOperator::EQ: o << "=="; break;
|
|
|
|
case RelationalOperator::NE: o << "/="; break;
|
|
|
|
case RelationalOperator::GE: o << ">="; break;
|
|
|
|
case RelationalOperator::GT: o << '>'; break;
|
|
|
|
}
|
|
|
|
return o;
|
2018-08-18 00:38:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-06 00:02:37 +01:00
|
|
|
std::ostream &Relational<SomeType>::AsFortran(std::ostream &o) const {
|
|
|
|
std::visit([&](const auto &rel) { rel.AsFortran(o); }, u);
|
2018-08-29 00:15:18 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2018-09-07 19:33:32 +02:00
|
|
|
template<int KIND>
|
|
|
|
std::ostream &LogicalOperation<KIND>::Infix(std::ostream &o) const {
|
2018-08-18 00:38:37 +02:00
|
|
|
switch (logicalOperator) {
|
2018-11-14 23:35:10 +01:00
|
|
|
case LogicalOperator::And: o << ".and."; break;
|
|
|
|
case LogicalOperator::Or: o << ".or."; break;
|
|
|
|
case LogicalOperator::Eqv: o << ".eqv."; break;
|
|
|
|
case LogicalOperator::Neqv: o << ".neqv."; break;
|
2018-08-18 00:38:37 +02:00
|
|
|
}
|
2018-09-07 19:33:32 +02:00
|
|
|
return o;
|
2018-08-18 00:38:37 +02:00
|
|
|
}
|
|
|
|
|
2018-10-30 23:24:35 +01:00
|
|
|
template<typename T>
|
|
|
|
std::ostream &Emit(std::ostream &o, const CopyableIndirection<Expr<T>> &expr) {
|
2018-11-06 00:02:37 +01:00
|
|
|
return expr->AsFortran(o);
|
2018-10-30 23:24:35 +01:00
|
|
|
}
|
2019-01-23 01:30:32 +01:00
|
|
|
|
2018-10-30 23:24:35 +01:00
|
|
|
template<typename T>
|
|
|
|
std::ostream &Emit(std::ostream &, const ArrayConstructorValues<T> &);
|
|
|
|
|
2019-01-23 01:30:32 +01:00
|
|
|
template<typename T>
|
|
|
|
std::ostream &Emit(std::ostream &o, const ImpliedDo<T> &implDo) {
|
2018-10-30 23:24:35 +01:00
|
|
|
o << '(';
|
|
|
|
Emit(o, *implDo.values);
|
2019-01-31 18:58:40 +01:00
|
|
|
o << ',' << ImpliedDoIndex::Result::AsFortran()
|
|
|
|
<< "::" << implDo.name.ToString() << '=';
|
2018-11-06 00:02:37 +01:00
|
|
|
implDo.lower->AsFortran(o) << ',';
|
|
|
|
implDo.upper->AsFortran(o) << ',';
|
|
|
|
implDo.stride->AsFortran(o) << ')';
|
2018-10-30 23:24:35 +01:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
std::ostream &Emit(std::ostream &o, const ArrayConstructorValues<T> &values) {
|
|
|
|
const char *sep{""};
|
|
|
|
for (const auto &value : values.values) {
|
|
|
|
o << sep;
|
|
|
|
std::visit([&](const auto &x) { Emit(o, x); }, value.u);
|
|
|
|
sep = ",";
|
|
|
|
}
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2018-11-06 00:02:37 +01:00
|
|
|
std::ostream &ArrayConstructor<T>::AsFortran(std::ostream &o) const {
|
2019-01-23 01:30:32 +01:00
|
|
|
o << '[' << GetType().AsFortran() << "::";
|
|
|
|
Emit(o, values);
|
|
|
|
return o << ']';
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
std::ostream &ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran(
|
|
|
|
std::ostream &o) const {
|
|
|
|
std::stringstream len;
|
|
|
|
length->AsFortran(len);
|
|
|
|
o << '[' << GetType().AsFortran(len.str()) << "::";
|
|
|
|
Emit(o, values);
|
2018-10-30 23:24:35 +01:00
|
|
|
return o << ']';
|
|
|
|
}
|
|
|
|
|
2018-08-29 00:15:18 +02:00
|
|
|
template<typename RESULT>
|
2018-11-06 00:02:37 +01:00
|
|
|
std::ostream &ExpressionBase<RESULT>::AsFortran(std::ostream &o) const {
|
|
|
|
std::visit(
|
2018-11-29 18:27:34 +01:00
|
|
|
common::visitors{
|
|
|
|
[&](const BOZLiteralConstant &x) {
|
|
|
|
o << "z'" << x.Hexadecimal() << "'";
|
|
|
|
},
|
2018-11-06 00:02:37 +01:00
|
|
|
[&](const CopyableIndirection<Substring> &s) { s->AsFortran(o); },
|
2019-01-23 01:30:32 +01:00
|
|
|
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
|
2018-11-29 18:27:34 +01:00
|
|
|
[&](const auto &x) { x.AsFortran(o); },
|
|
|
|
},
|
2018-08-29 00:15:18 +02:00
|
|
|
derived().u);
|
2018-08-18 00:38:37 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
Expr<SubscriptInteger> Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
|
2018-07-19 19:12:25 +02:00
|
|
|
return std::visit(
|
2018-11-29 18:27:34 +01:00
|
|
|
common::visitors{
|
|
|
|
[](const Constant<Result> &c) {
|
2019-02-01 22:37:49 +01:00
|
|
|
return AsExpr(Constant<SubscriptInteger>{ConstantLEN(c)});
|
2018-11-29 18:27:34 +01:00
|
|
|
},
|
2018-10-31 00:25:10 +01:00
|
|
|
[](const ArrayConstructor<Result> &a) { return a.LEN(); },
|
2018-09-17 20:31:38 +02:00
|
|
|
[](const Parentheses<Result> &x) { return x.left().LEN(); },
|
2018-08-18 00:38:37 +02:00
|
|
|
[](const Concat<KIND> &c) {
|
2018-09-17 20:31:38 +02:00
|
|
|
return c.left().LEN() + c.right().LEN();
|
2018-08-09 01:30:58 +02:00
|
|
|
},
|
2018-08-18 00:38:37 +02:00
|
|
|
[](const Extremum<Result> &c) {
|
2018-09-07 19:33:32 +02:00
|
|
|
return Expr<SubscriptInteger>{
|
|
|
|
Extremum<SubscriptInteger>{c.left().LEN(), c.right().LEN()}};
|
2018-08-18 00:38:37 +02:00
|
|
|
},
|
2018-09-15 00:48:40 +02:00
|
|
|
[](const Designator<Result> &dr) { return dr.LEN(); },
|
2018-11-29 18:27:34 +01:00
|
|
|
[](const FunctionRef<Result> &fr) { return fr.LEN(); },
|
|
|
|
},
|
2018-07-20 21:19:09 +02:00
|
|
|
u);
|
2018-07-19 18:53:42 +02:00
|
|
|
}
|
|
|
|
|
2018-09-07 19:33:32 +02:00
|
|
|
Expr<SomeType>::~Expr() {}
|
|
|
|
|
2019-01-03 17:45:27 +01:00
|
|
|
#if defined(__APPLE__) && defined(__GNUC__)
|
2018-12-20 18:39:29 +01:00
|
|
|
template<typename A>
|
|
|
|
typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() {
|
|
|
|
return *static_cast<Derived *>(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A>
|
|
|
|
const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const {
|
|
|
|
return *static_cast<const Derived *>(this);
|
|
|
|
}
|
2019-01-03 17:45:27 +01:00
|
|
|
#endif
|
2018-12-20 18:39:29 +01:00
|
|
|
|
2018-10-09 00:35:19 +02:00
|
|
|
template<typename A>
|
|
|
|
std::optional<DynamicType> ExpressionBase<A>::GetType() const {
|
2019-01-04 23:05:53 +01:00
|
|
|
if constexpr (IsLengthlessIntrinsicType<Result>) {
|
2018-10-09 21:07:29 +02:00
|
|
|
return Result::GetType();
|
2018-10-09 00:35:19 +02:00
|
|
|
} else {
|
|
|
|
return std::visit(
|
|
|
|
[](const auto &x) -> std::optional<DynamicType> {
|
2018-10-15 21:17:30 +02:00
|
|
|
if constexpr (!std::is_same_v<std::decay_t<decltype(x)>,
|
2018-10-09 00:35:19 +02:00
|
|
|
BOZLiteralConstant>) {
|
|
|
|
return x.GetType();
|
|
|
|
}
|
2019-01-04 23:05:53 +01:00
|
|
|
return std::nullopt; // typeless really means "no type"
|
2018-10-09 00:35:19 +02:00
|
|
|
},
|
|
|
|
derived().u);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-18 18:34:59 +02:00
|
|
|
template<typename A> int ExpressionBase<A>::Rank() const {
|
|
|
|
return std::visit(
|
2018-10-01 23:36:31 +02:00
|
|
|
[](const auto &x) {
|
|
|
|
if constexpr (std::is_same_v<std::decay_t<decltype(x)>,
|
|
|
|
BOZLiteralConstant>) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return x.Rank();
|
|
|
|
}
|
|
|
|
},
|
2018-09-18 18:34:59 +02:00
|
|
|
derived().u);
|
|
|
|
}
|
|
|
|
|
2019-01-23 01:30:32 +01:00
|
|
|
template<int KIND>
|
|
|
|
ArrayConstructor<Type<TypeCategory::Character, KIND>>::~ArrayConstructor() {}
|
|
|
|
|
2019-01-04 23:05:53 +01:00
|
|
|
// Equality testing for classes without EVALUATE_UNION_CLASS_BOILERPLATE()
|
|
|
|
|
2019-01-23 01:30:32 +01:00
|
|
|
bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
|
|
|
|
return name == that.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const {
|
2019-01-31 18:58:40 +01:00
|
|
|
return name == that.name && lower == that.lower && upper == that.upper &&
|
|
|
|
stride == that.stride && values == that.values;
|
2019-01-04 23:05:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
bool ArrayConstructorValues<R>::operator==(
|
|
|
|
const ArrayConstructorValues<R> &that) const {
|
|
|
|
return values == that.values;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
bool ArrayConstructor<R>::operator==(const ArrayConstructor<R> &that) const {
|
2019-01-23 01:30:32 +01:00
|
|
|
return type == that.type && values == that.values;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
|
|
|
|
const ArrayConstructor<Type<TypeCategory::Character, KIND>> &that) const {
|
|
|
|
return length == that.length && values == that.values;
|
2019-01-04 23:05:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GenericExprWrapper::operator==(const GenericExprWrapper &that) const {
|
|
|
|
return v == that.v;
|
|
|
|
}
|
|
|
|
|
2018-08-29 00:15:18 +02:00
|
|
|
// Template instantiations to resolve the "extern template" declarations
|
2018-09-12 20:20:30 +02:00
|
|
|
// that appear in expression.h.
|
2018-08-18 00:38:37 +02:00
|
|
|
|
2018-10-27 01:31:20 +02:00
|
|
|
FOR_EACH_INTRINSIC_KIND(template class Expr)
|
|
|
|
FOR_EACH_CATEGORY_TYPE(template class Expr)
|
|
|
|
FOR_EACH_INTEGER_KIND(template struct Relational)
|
|
|
|
FOR_EACH_REAL_KIND(template struct Relational)
|
|
|
|
FOR_EACH_CHARACTER_KIND(template struct Relational)
|
2018-08-29 00:15:18 +02:00
|
|
|
template struct Relational<SomeType>;
|
2018-10-30 20:44:09 +01:00
|
|
|
FOR_EACH_TYPE_AND_KIND(template class ExpressionBase)
|
2019-01-04 23:05:53 +01:00
|
|
|
FOR_EACH_SPECIFIC_TYPE(template struct ArrayConstructor)
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|
2018-09-07 19:33:32 +02:00
|
|
|
|
|
|
|
// For reclamation of analyzed expressions to which owning pointers have
|
|
|
|
// been embedded in the parse tree. This destructor appears here, where
|
|
|
|
// definitions for all the necessary types are available, to obviate a
|
|
|
|
// need to include lib/evaluate/*.h headers in the parser proper.
|
|
|
|
namespace Fortran::common {
|
|
|
|
template<> OwningPointer<evaluate::GenericExprWrapper>::~OwningPointer() {
|
|
|
|
delete p_;
|
|
|
|
p_ = nullptr;
|
|
|
|
}
|
|
|
|
template class OwningPointer<evaluate::GenericExprWrapper>;
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|