forked from OSchip/llvm-project
[flang] checkpoint array/struct constructor work
Original-commit: flang-compiler/f18@b0a574fa35 Reviewed-on: https://github.com/flang-compiler/f18/pull/287 Tree-same-pre-rewrite: false
This commit is contained in:
parent
25807d88f4
commit
4313f4c762
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
-->
|
||||
|
||||
As a general principle, this compiler will accept by default and
|
||||
|
@ -79,3 +79,4 @@ Extensions and legacy features deliberately not supported
|
|||
* `B` suffix on unquoted octal constants
|
||||
* `Z` prefix on unquoted hexadecimal constants (dangerous)
|
||||
* `T` and `F` as abbreviations for `.TRUE.` and `.FALSE.` (dangerous)
|
||||
* Use of host FORMAT labels in internal subprograms (PGI-only feature)
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
template<typename T> ConstantBase<T>::~ConstantBase() {}
|
||||
template<typename RESULT, typename VALUE>
|
||||
ConstantBase<RESULT, VALUE>::~ConstantBase() {}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &ConstantBase<T>::AsFortran(std::ostream &o) const {
|
||||
template<typename RESULT, typename VALUE>
|
||||
std::ostream &ConstantBase<RESULT, VALUE>::AsFortran(std::ostream &o) const {
|
||||
if (Rank() > 1) {
|
||||
o << "reshape(";
|
||||
}
|
||||
|
@ -36,14 +37,14 @@ std::ostream &ConstantBase<T>::AsFortran(std::ostream &o) const {
|
|||
} else {
|
||||
o << ',';
|
||||
}
|
||||
if constexpr (T::category == TypeCategory::Integer) {
|
||||
o << value.SignedDecimal() << '_' << T::kind;
|
||||
} else if constexpr (T::category == TypeCategory::Real ||
|
||||
T::category == TypeCategory::Complex) {
|
||||
value.AsFortran(o, T::kind);
|
||||
} else if constexpr (T::category == TypeCategory::Character) {
|
||||
o << T::kind << '_' << parser::QuoteCharacterLiteral(value);
|
||||
} else if constexpr (T::category == TypeCategory::Logical) {
|
||||
if constexpr (Result::category == TypeCategory::Integer) {
|
||||
o << value.SignedDecimal() << '_' << Result::kind;
|
||||
} else if constexpr (Result::category == TypeCategory::Real ||
|
||||
Result::category == TypeCategory::Complex) {
|
||||
value.AsFortran(o, Result::kind);
|
||||
} else if constexpr (Result::category == TypeCategory::Character) {
|
||||
o << Result::kind << '_' << parser::QuoteCharacterLiteral(value);
|
||||
} else if constexpr (Result::category == TypeCategory::Logical) {
|
||||
if (value.IsTrue()) {
|
||||
o << ".true.";
|
||||
} else {
|
||||
|
@ -51,7 +52,7 @@ std::ostream &ConstantBase<T>::AsFortran(std::ostream &o) const {
|
|||
}
|
||||
o << '_' << Result::kind;
|
||||
} else {
|
||||
value.AsFortran(o);
|
||||
StructureConstructor{AsConstant().derivedTypeSpec(), value}.AsFortran(o);
|
||||
}
|
||||
}
|
||||
if (Rank() > 0) {
|
||||
|
@ -69,9 +70,9 @@ std::ostream &ConstantBase<T>::AsFortran(std::ostream &o) const {
|
|||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto ConstantBase<T>::At(const std::vector<std::int64_t> &index) const
|
||||
-> Value {
|
||||
template<typename RESULT, typename VALUE>
|
||||
auto ConstantBase<RESULT, VALUE>::At(
|
||||
const std::vector<std::int64_t> &index) const -> Value {
|
||||
CHECK(index.size() == static_cast<std::size_t>(Rank()));
|
||||
std::int64_t stride{1}, offset{0};
|
||||
int dim{0};
|
||||
|
@ -84,7 +85,8 @@ auto ConstantBase<T>::At(const std::vector<std::int64_t> &index) const
|
|||
return values_.at(offset);
|
||||
}
|
||||
|
||||
template<typename T> Constant<SubscriptInteger> ConstantBase<T>::SHAPE() const {
|
||||
template<typename RESULT, typename VALUE>
|
||||
Constant<SubscriptInteger> ConstantBase<RESULT, VALUE>::SHAPE() const {
|
||||
using IntType = Scalar<SubscriptInteger>;
|
||||
std::vector<IntType> result;
|
||||
for (std::int64_t dim : shape_) {
|
||||
|
@ -93,10 +95,30 @@ template<typename T> Constant<SubscriptInteger> ConstantBase<T>::SHAPE() const {
|
|||
return {std::move(result), std::vector<std::int64_t>{Rank()}};
|
||||
}
|
||||
|
||||
Constant<SomeDerived>::Constant(const StructureConstructor &x)
|
||||
: Base{x.values()}, derivedTypeSpec_{&x.derivedTypeSpec()} {}
|
||||
|
||||
Constant<SomeDerived>::Constant(StructureConstructor &&x)
|
||||
: Base{std::move(x.values())}, derivedTypeSpec_{&x.derivedTypeSpec()} {}
|
||||
|
||||
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
|
||||
std::vector<StructureConstructorValues> &&x, std::vector<std::int64_t> &&s)
|
||||
: Base{std::move(x), std::move(s)}, derivedTypeSpec_{&spec} {}
|
||||
|
||||
static std::vector<StructureConstructorValues> GetValues(
|
||||
std::vector<StructureConstructor> &&x) {
|
||||
std::vector<StructureConstructorValues> result;
|
||||
for (auto &&structure : std::move(x)) {
|
||||
result.emplace_back(std::move(structure.values()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
|
||||
std::vector<StructureConstructor> &&x, std::vector<std::int64_t> &&s)
|
||||
: Base{std::move(x), std::move(s)}, spec_{&spec} {}
|
||||
: Base{GetValues(std::move(x)), std::move(s)}, derivedTypeSpec_{&spec} {}
|
||||
|
||||
FOR_EACH_SPECIFIC_TYPE(template class ConstantBase)
|
||||
FOR_EACH_INTRINSIC_KIND(template class ConstantBase)
|
||||
template class ConstantBase<SomeDerived, StructureConstructorValues>;
|
||||
FOR_EACH_INTRINSIC_KIND(template class Constant)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define FORTRAN_EVALUATE_CONSTANT_H_
|
||||
|
||||
#include "type.h"
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
@ -27,10 +28,10 @@ namespace Fortran::evaluate {
|
|||
|
||||
template<typename> class Constant;
|
||||
|
||||
template<typename RESULT> class ConstantBase {
|
||||
template<typename RESULT, typename VALUE = Scalar<RESULT>> class ConstantBase {
|
||||
public:
|
||||
using Result = RESULT;
|
||||
using Value = Scalar<Result>;
|
||||
using Value = VALUE;
|
||||
|
||||
template<typename A> ConstantBase(const A &x) : values_{x} {}
|
||||
template<typename A>
|
||||
|
@ -97,30 +98,37 @@ public:
|
|||
// TODO pmk: make CHARACTER values contiguous (they're strings now)
|
||||
};
|
||||
|
||||
template<> class Constant<SomeDerived> : public ConstantBase<SomeDerived> {
|
||||
using StructureConstructorValues =
|
||||
std::map<const semantics::Symbol *, CopyableIndirection<Expr<SomeType>>>;
|
||||
|
||||
template<>
|
||||
class Constant<SomeDerived>
|
||||
: public ConstantBase<SomeDerived, StructureConstructorValues> {
|
||||
public:
|
||||
using Result = SomeDerived;
|
||||
using Base = ConstantBase<Result>;
|
||||
template<typename A>
|
||||
Constant(const semantics::DerivedTypeSpec &spec, const A &x)
|
||||
: Base{x}, spec_{&spec} {}
|
||||
template<typename A>
|
||||
Constant(const semantics::DerivedTypeSpec &spec,
|
||||
std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
: Base{std::move(x)}, spec_{&spec} {}
|
||||
using Base = ConstantBase<Result, StructureConstructorValues>;
|
||||
Constant(const StructureConstructor &);
|
||||
Constant(StructureConstructor &&);
|
||||
Constant(const semantics::DerivedTypeSpec &, std::vector<Value> &&,
|
||||
std::vector<std::int64_t> &&);
|
||||
|
||||
Constant(const semantics::DerivedTypeSpec &,
|
||||
std::vector<StructureConstructor> &&, std::vector<std::int64_t> &&);
|
||||
CLASS_BOILERPLATE(Constant)
|
||||
|
||||
const semantics::DerivedTypeSpec &derivedTypeSpec() const {
|
||||
return *derivedTypeSpec_;
|
||||
}
|
||||
|
||||
DynamicType GetType() const {
|
||||
return DynamicType{TypeCategory::Derived, 0, spec_};
|
||||
return DynamicType{TypeCategory::Derived, 0, derivedTypeSpec_};
|
||||
}
|
||||
|
||||
private:
|
||||
const semantics::DerivedTypeSpec *spec_;
|
||||
const semantics::DerivedTypeSpec *derivedTypeSpec_;
|
||||
};
|
||||
|
||||
FOR_EACH_SPECIFIC_TYPE(extern template class ConstantBase)
|
||||
FOR_EACH_INTRINSIC_KIND(extern template class ConstantBase)
|
||||
extern template class ConstantBase<SomeDerived, StructureConstructorValues>;
|
||||
FOR_EACH_INTRINSIC_KIND(extern template class Constant)
|
||||
}
|
||||
#endif // FORTRAN_EVALUATE_CONSTANT_H_
|
||||
|
|
|
@ -130,6 +130,12 @@ std::ostream &ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran(
|
|||
return o << ']';
|
||||
}
|
||||
|
||||
std::ostream &ArrayConstructor<SomeDerived>::AsFortran(std::ostream &o) const {
|
||||
o << '[' << GetType().AsFortran() << "::";
|
||||
Emit(o, values);
|
||||
return o << ']';
|
||||
}
|
||||
|
||||
template<typename RESULT>
|
||||
std::ostream &ExpressionBase<RESULT>::AsFortran(std::ostream &o) const {
|
||||
std::visit(
|
||||
|
@ -234,7 +240,7 @@ bool ArrayConstructorValues<R>::operator==(
|
|||
|
||||
template<typename R>
|
||||
bool ArrayConstructor<R>::operator==(const ArrayConstructor<R> &that) const {
|
||||
return type == that.type && values == that.values;
|
||||
return values == that.values;
|
||||
}
|
||||
|
||||
template<int KIND>
|
||||
|
@ -243,6 +249,78 @@ bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
|
|||
return length == that.length && values == that.values;
|
||||
}
|
||||
|
||||
bool ArrayConstructor<SomeDerived>::operator==(
|
||||
const ArrayConstructor<SomeDerived> &that) const {
|
||||
return derivedTypeSpec_ == that.derivedTypeSpec_ && values == that.values;
|
||||
}
|
||||
|
||||
StructureConstructor::StructureConstructor(
|
||||
const semantics::DerivedTypeSpec &spec,
|
||||
const StructureConstructorValues &values)
|
||||
: derivedTypeSpec_{&spec}, values_{values} {}
|
||||
StructureConstructor::StructureConstructor(
|
||||
const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values)
|
||||
: derivedTypeSpec_{&spec}, values_{std::move(values)} {}
|
||||
StructureConstructor::StructureConstructor(const StructureConstructor &that)
|
||||
: derivedTypeSpec_{that.derivedTypeSpec_}, values_{that.values_} {}
|
||||
StructureConstructor::StructureConstructor(StructureConstructor &&that)
|
||||
: derivedTypeSpec_{that.derivedTypeSpec_}, values_{std::move(that.values_)} {}
|
||||
StructureConstructor::~StructureConstructor() {}
|
||||
StructureConstructor &StructureConstructor::operator=(
|
||||
const StructureConstructor &that) {
|
||||
derivedTypeSpec_ = that.derivedTypeSpec_;
|
||||
values_ = that.values_;
|
||||
return *this;
|
||||
}
|
||||
StructureConstructor &StructureConstructor::operator=(
|
||||
StructureConstructor &&that) {
|
||||
derivedTypeSpec_ = that.derivedTypeSpec_;
|
||||
values_ = std::move(that.values_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool StructureConstructor::operator==(const StructureConstructor &that) const {
|
||||
return derivedTypeSpec_ == that.derivedTypeSpec_ && values_ == that.values_;
|
||||
}
|
||||
|
||||
DynamicType StructureConstructor::GetType() const {
|
||||
return {TypeCategory::Derived, 0, derivedTypeSpec_};
|
||||
}
|
||||
|
||||
StructureConstructor &StructureConstructor::Add(
|
||||
const Symbol &symbol, Expr<SomeType> &&expr) {
|
||||
values_.emplace(&symbol, std::move(expr));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostream &StructureConstructor::AsFortran(std::ostream &o) const {
|
||||
DerivedTypeSpecAsFortran(o, *derivedTypeSpec_);
|
||||
if (values_.empty()) {
|
||||
o << '(';
|
||||
} else {
|
||||
char ch{'('};
|
||||
for (const auto &[symbol, value] : values_) {
|
||||
value->AsFortran(o << ch << symbol->name().ToString() << '=');
|
||||
ch = ',';
|
||||
}
|
||||
}
|
||||
return o << ')';
|
||||
}
|
||||
|
||||
std::ostream &DerivedTypeSpecAsFortran(
|
||||
std::ostream &o, const semantics::DerivedTypeSpec &spec) {
|
||||
o << "TYPE("s << spec.typeSymbol().name().ToString();
|
||||
if (!spec.parameters().empty()) {
|
||||
char ch{'('};
|
||||
for (const auto &[name, value] : spec.parameters()) {
|
||||
value.GetExplicit()->AsFortran(o << ch << name.ToString() << '=');
|
||||
ch = ',';
|
||||
}
|
||||
o << ')';
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
bool GenericExprWrapper::operator==(const GenericExprWrapper &that) const {
|
||||
return v == that.v;
|
||||
}
|
||||
|
@ -257,7 +335,7 @@ FOR_EACH_REAL_KIND(template struct Relational)
|
|||
FOR_EACH_CHARACTER_KIND(template struct Relational)
|
||||
template struct Relational<SomeType>;
|
||||
FOR_EACH_TYPE_AND_KIND(template class ExpressionBase)
|
||||
FOR_EACH_SPECIFIC_TYPE(template struct ArrayConstructor)
|
||||
FOR_EACH_INTRINSIC_KIND(template struct ArrayConstructor)
|
||||
}
|
||||
|
||||
// For reclamation of analyzed expressions to which owning pointers have
|
||||
|
|
|
@ -425,18 +425,15 @@ template<typename RESULT> struct ArrayConstructorValues {
|
|||
std::vector<ArrayConstructorValue<Result>> values;
|
||||
};
|
||||
|
||||
// TODO pmk: use a common base class as with Constant
|
||||
template<typename RESULT> struct ArrayConstructor {
|
||||
using Result = RESULT;
|
||||
CLASS_BOILERPLATE(ArrayConstructor)
|
||||
ArrayConstructor(Result &&t, ArrayConstructorValues<Result> &&v)
|
||||
: type{std::move(t)}, values{std::move(v)} {
|
||||
CHECK(type.category != TypeCategory::Character);
|
||||
}
|
||||
ArrayConstructor(ArrayConstructorValues<Result> &&v) : values{std::move(v)} {}
|
||||
bool operator==(const ArrayConstructor<RESULT> &) const;
|
||||
DynamicType GetType() const { return type.GetType(); }
|
||||
static constexpr DynamicType GetType() { return Result::GetType(); }
|
||||
static constexpr int Rank() { return 1; }
|
||||
std::ostream &AsFortran(std::ostream &) const;
|
||||
Result type;
|
||||
ArrayConstructorValues<Result> values;
|
||||
};
|
||||
|
||||
|
@ -445,8 +442,8 @@ struct ArrayConstructor<Type<TypeCategory::Character, KIND>> {
|
|||
using Result = Type<TypeCategory::Character, KIND>;
|
||||
CLASS_BOILERPLATE(ArrayConstructor)
|
||||
ArrayConstructor(
|
||||
ArrayConstructorValues<Result> &&v, Expr<SubscriptInteger> &&len)
|
||||
: values{std::move(v)}, length{std::move(len)} {}
|
||||
Expr<SubscriptInteger> &&len, ArrayConstructorValues<Result> &&v)
|
||||
: length{std::move(len)}, values{std::move(v)} {}
|
||||
~ArrayConstructor();
|
||||
bool operator==(const ArrayConstructor<Result> &) const;
|
||||
static constexpr DynamicType GetType() { return Result::GetType(); }
|
||||
|
@ -454,8 +451,27 @@ struct ArrayConstructor<Type<TypeCategory::Character, KIND>> {
|
|||
std::ostream &AsFortran(std::ostream &) const;
|
||||
const Expr<SubscriptInteger> &LEN() const { return *length; }
|
||||
|
||||
ArrayConstructorValues<Result> values;
|
||||
CopyableIndirection<Expr<SubscriptInteger>> length;
|
||||
ArrayConstructorValues<Result> values;
|
||||
};
|
||||
|
||||
template<> struct ArrayConstructor<SomeDerived> {
|
||||
using Result = SomeDerived;
|
||||
CLASS_BOILERPLATE(ArrayConstructor)
|
||||
ArrayConstructor(const semantics::DerivedTypeSpec &spec,
|
||||
ArrayConstructorValues<Result> &&v)
|
||||
: derivedTypeSpec_{&spec}, values{std::move(v)} {}
|
||||
bool operator==(const ArrayConstructor<Result> &) const;
|
||||
const semantics::DerivedTypeSpec &derivedTypeSpec() const {
|
||||
return *derivedTypeSpec_;
|
||||
}
|
||||
DynamicType GetType() const {
|
||||
return DynamicType{TypeCategory::Derived, 0, derivedTypeSpec_};
|
||||
}
|
||||
static constexpr int Rank() { return 1; }
|
||||
std::ostream &AsFortran(std::ostream &) const;
|
||||
const semantics::DerivedTypeSpec *derivedTypeSpec_;
|
||||
ArrayConstructorValues<Result> values;
|
||||
};
|
||||
|
||||
// Expression representations for each type category.
|
||||
|
@ -635,15 +651,16 @@ FOR_EACH_LOGICAL_KIND(extern template class Expr)
|
|||
|
||||
class StructureConstructor {
|
||||
public:
|
||||
using Values = std::list<std::pair<const semantics::Symbol *,
|
||||
CopyableIndirection<Expr<SomeType>>>>;
|
||||
|
||||
// N.B. CLASS_BOILERPLATE() can't be used here due to forward reference
|
||||
// to Expr<SomeType> preventing the use of "= default" constructors and
|
||||
// assignment operators.
|
||||
StructureConstructor() = delete;
|
||||
explicit StructureConstructor(const semantics::DerivedTypeSpec &spec)
|
||||
: derivedTypeSpec_{&spec} {}
|
||||
StructureConstructor(
|
||||
const semantics::DerivedTypeSpec &, const StructureConstructorValues &);
|
||||
StructureConstructor(
|
||||
const semantics::DerivedTypeSpec &, StructureConstructorValues &&);
|
||||
StructureConstructor(const StructureConstructor &);
|
||||
StructureConstructor(StructureConstructor &&);
|
||||
~StructureConstructor();
|
||||
|
@ -653,8 +670,8 @@ public:
|
|||
const semantics::DerivedTypeSpec &derivedTypeSpec() const {
|
||||
return *derivedTypeSpec_;
|
||||
}
|
||||
Values &values() { return values_; }
|
||||
const Values &values() const { return values_; }
|
||||
StructureConstructorValues &values() { return values_; }
|
||||
const StructureConstructorValues &values() const { return values_; }
|
||||
bool operator==(const StructureConstructor &) const;
|
||||
|
||||
StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
|
||||
|
@ -664,7 +681,7 @@ public:
|
|||
|
||||
private:
|
||||
const semantics::DerivedTypeSpec *derivedTypeSpec_;
|
||||
Values values_;
|
||||
StructureConstructorValues values_;
|
||||
};
|
||||
|
||||
// An expression whose result has a derived type.
|
||||
|
@ -741,8 +758,11 @@ struct GenericExprWrapper {
|
|||
Expr<SomeType> v;
|
||||
};
|
||||
|
||||
std::ostream &DerivedTypeSpecAsFortran(
|
||||
std::ostream &, const semantics::DerivedTypeSpec &);
|
||||
|
||||
FOR_EACH_CATEGORY_TYPE(extern template class Expr)
|
||||
FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase)
|
||||
FOR_EACH_SPECIFIC_TYPE(extern template struct ArrayConstructor)
|
||||
FOR_EACH_INTRINSIC_KIND(extern template struct ArrayConstructor)
|
||||
}
|
||||
#endif // FORTRAN_EVALUATE_EXPRESSION_H_
|
||||
|
|
|
@ -230,10 +230,10 @@ public:
|
|||
|
||||
Expr<T> FoldArray(ArrayConstructor<T> &&array) {
|
||||
if (FoldArray(array.values)) {
|
||||
std::int64_t n = elements_.size();
|
||||
auto n{static_cast<std::int64_t>(elements_.size())};
|
||||
if constexpr (std::is_same_v<T, SomeDerived>) {
|
||||
return Expr<T>{Constant<T>{array.type.spec(), std::move(elements_),
|
||||
std::vector<std::int64_t>{n}}};
|
||||
return Expr<T>{Constant<T>{array.derivedTypeSpec(),
|
||||
std::move(elements_), std::vector<std::int64_t>{n}}};
|
||||
} else {
|
||||
return Expr<T>{
|
||||
Constant<T>{std::move(elements_), std::vector<std::int64_t>{n}}};
|
||||
|
@ -252,7 +252,11 @@ private:
|
|||
int rank{c->Rank()};
|
||||
std::vector<std::int64_t> index(shape.size(), 1);
|
||||
for (std::size_t n{c->size()}; n-- > 0;) {
|
||||
elements_.push_back(c->At(index));
|
||||
if constexpr (std::is_same_v<T, SomeDerived>) {
|
||||
elements_.emplace_back(c->derivedTypeSpec(), c->At(index));
|
||||
} else {
|
||||
elements_.emplace_back(c->At(index));
|
||||
}
|
||||
for (int d{0}; d < rank; ++d) {
|
||||
if (++index[d] <= shape[d]) {
|
||||
break;
|
||||
|
@ -315,8 +319,7 @@ Expr<SomeDerived> FoldOperation(
|
|||
for (auto &&[symbol, value] : std::move(structure.values())) {
|
||||
result.Add(*symbol, Fold(context, std::move(*value)));
|
||||
}
|
||||
return Expr<SomeDerived>{
|
||||
Constant<SomeDerived>{result.derivedTypeSpec(), result}};
|
||||
return Expr<SomeDerived>{Constant<SomeDerived>{result}};
|
||||
}
|
||||
|
||||
// Substitute a bare type parameter reference with its value if it has one now
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "../semantics/type.h"
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
@ -185,69 +184,9 @@ bool SomeKind<TypeCategory::Derived>::operator==(
|
|||
return spec_ == that.spec_ && descriptor_ == that.descriptor_;
|
||||
}
|
||||
|
||||
static std::ostream &DerivedTypeSpecAsFortran(
|
||||
std::ostream &o, const semantics::DerivedTypeSpec &spec) {
|
||||
o << "TYPE("s << spec.typeSymbol().name().ToString();
|
||||
if (!spec.parameters().empty()) {
|
||||
char ch{'('};
|
||||
for (const auto &[name, value] : spec.parameters()) {
|
||||
value.GetExplicit()->AsFortran(o << ch << name.ToString() << '=');
|
||||
ch = ',';
|
||||
}
|
||||
o << ')';
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
std::string SomeDerived::AsFortran() const {
|
||||
std::stringstream out;
|
||||
DerivedTypeSpecAsFortran(out, spec());
|
||||
return out.str();
|
||||
}
|
||||
|
||||
StructureConstructor::StructureConstructor(const StructureConstructor &that)
|
||||
: derivedTypeSpec_{that.derivedTypeSpec_}, values_{that.values_} {}
|
||||
StructureConstructor::StructureConstructor(StructureConstructor &&that)
|
||||
: derivedTypeSpec_{that.derivedTypeSpec_}, values_{std::move(that.values_)} {}
|
||||
StructureConstructor::~StructureConstructor() {}
|
||||
StructureConstructor &StructureConstructor::operator=(
|
||||
const StructureConstructor &that) {
|
||||
derivedTypeSpec_ = that.derivedTypeSpec_;
|
||||
values_ = that.values_;
|
||||
return *this;
|
||||
}
|
||||
StructureConstructor &StructureConstructor::operator=(
|
||||
StructureConstructor &&that) {
|
||||
derivedTypeSpec_ = that.derivedTypeSpec_;
|
||||
values_ = std::move(that.values_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool StructureConstructor::operator==(const StructureConstructor &that) const {
|
||||
return derivedTypeSpec_ == that.derivedTypeSpec_ && values_ == that.values_;
|
||||
}
|
||||
|
||||
DynamicType StructureConstructor::GetType() const {
|
||||
return {TypeCategory::Derived, 0, derivedTypeSpec_};
|
||||
}
|
||||
|
||||
StructureConstructor &StructureConstructor::Add(
|
||||
const Symbol &symbol, Expr<SomeType> &&expr) {
|
||||
values_.emplace_back(&symbol, std::move(expr));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostream &StructureConstructor::AsFortran(std::ostream &o) const {
|
||||
DerivedTypeSpecAsFortran(o, *derivedTypeSpec_);
|
||||
if (values_.empty()) {
|
||||
o << '(';
|
||||
} else {
|
||||
char ch{'('};
|
||||
for (const auto &[symbol, value] : values_) {
|
||||
value->AsFortran(o << ch << symbol->name().ToString() << '=');
|
||||
ch = ',';
|
||||
}
|
||||
}
|
||||
return o << ')';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -288,6 +288,9 @@ using SomeDerived = SomeKind<TypeCategory::Derived>;
|
|||
using SomeCategory = std::tuple<SomeInteger, SomeReal, SomeComplex,
|
||||
SomeCharacter, SomeLogical, SomeDerived>;
|
||||
|
||||
using AllTypes =
|
||||
common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
|
||||
|
||||
template<typename T> using Scalar = typename std::decay_t<T>::Scalar;
|
||||
|
||||
// When Scalar<T> is S, then TypeOf<S> is T.
|
||||
|
|
|
@ -1284,20 +1284,25 @@ ArrayConstructorValues<T> MakeSpecific(
|
|||
|
||||
struct ArrayConstructorTypeVisitor {
|
||||
using Result = MaybeExpr;
|
||||
using Types = LengthlessIntrinsicTypes;
|
||||
using Types = AllTypes;
|
||||
template<typename T> Result Test() {
|
||||
if (type.category == T::category && type.kind == T::kind) {
|
||||
if constexpr (T::category == TypeCategory::Character) {
|
||||
CHECK(type.length.has_value());
|
||||
if (type.category == T::category) {
|
||||
if constexpr (T::category == TypeCategory::Derived) {
|
||||
CHECK(type.derived != nullptr);
|
||||
return AsMaybeExpr(ArrayConstructor<T>{
|
||||
MakeSpecific<T>(std::move(values)), std::move(*type.length)});
|
||||
} else {
|
||||
return AsMaybeExpr(
|
||||
ArrayConstructor<T>{T{}, MakeSpecific<T>(std::move(values))});
|
||||
*type.derived, MakeSpecific<T>(std::move(values))});
|
||||
} else if (type.kind == T::kind) {
|
||||
if constexpr (T::category == TypeCategory::Character) {
|
||||
CHECK(type.length.has_value());
|
||||
return AsMaybeExpr(ArrayConstructor<T>{
|
||||
std::move(*type.length), MakeSpecific<T>(std::move(values))});
|
||||
} else {
|
||||
return AsMaybeExpr(
|
||||
ArrayConstructor<T>{MakeSpecific<T>(std::move(values))});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
DynamicTypeWithLength type;
|
||||
ArrayConstructorValues<SomeType> values;
|
||||
|
|
|
@ -113,7 +113,15 @@ set(MODFILE_TESTS
|
|||
)
|
||||
|
||||
set(LABEL_TESTS
|
||||
label*.[Ff]90
|
||||
# label*.[Ff]90 # 01, 05, 06, 07 loop with current master
|
||||
label02.f90
|
||||
label03.f90
|
||||
label04.f90
|
||||
label08.f90
|
||||
label09.f90
|
||||
label10.f90
|
||||
label11.f90
|
||||
label12.f90
|
||||
)
|
||||
|
||||
set(DOCONCURRENT_TESTS
|
||||
|
|
Loading…
Reference in New Issue