// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. // // 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. #ifndef FORTRAN_EVALUATE_CONSTANT_H_ #define FORTRAN_EVALUATE_CONSTANT_H_ #include "type.h" #include #include namespace Fortran::evaluate { // Wraps a constant value in a class templated by its resolved type. // This Constant<> template class should be instantiated only for // concrete intrinsic types and SomeDerived. There is no instance // Constant> since there is no way to constrain each // element of its array to hold the same type. To represent a generic // constants, use a generic expression like Expr & // Expr) to wrap the appropriate instantiation of Constant<>. template class Constant; // Constant<> is specialized for Character kinds and SomeDerived. // The non-Character intrinsic types, and SomeDerived, share enough // common behavior that they use this common base class. template> class ConstantBase { static_assert(RESULT::category != TypeCategory::Character); public: using Result = RESULT; using ScalarValue = SCALAR; template ConstantBase(const A &x) : values_{x} {} template ConstantBase(std::enable_if_t, A> &&x) : values_{std::move(x)} {} ConstantBase(std::vector &&x, std::vector &&dims) : values_(std::move(x)), shape_(std::move(dims)) {} ~ConstantBase(); int Rank() const { return static_cast(shape_.size()); } bool operator==(const ConstantBase &that) const { return shape_ == that.shape_ && values_ == that.values_; } bool empty() const { return values_.empty(); } std::size_t size() const { return values_.size(); } const std::vector &shape() const { return shape_; } ScalarValue operator*() const { CHECK(values_.size() == 1); return values_.at(0); } // Apply 1-based subscripts ScalarValue At(const std::vector &) const; Constant SHAPE() const; std::ostream &AsFortran(std::ostream &) const; protected: std::vector values_; std::vector shape_; private: const Constant &AsConstant() const { return *static_cast *>(this); } DynamicType GetType() const { return AsConstant().GetType(); } }; template class Constant : public ConstantBase { public: using Result = T; using ScalarValue = Scalar; using ConstantBase::ConstantBase; CLASS_BOILERPLATE(Constant) static constexpr DynamicType GetType() { return Result::GetType(); } }; template class Constant> { public: using Result = Type; using ScalarValue = Scalar; CLASS_BOILERPLATE(Constant) explicit Constant(const ScalarValue &); explicit Constant(ScalarValue &&); Constant( std::int64_t, std::vector &&, std::vector &&); ~Constant(); int Rank() const { return static_cast(shape_.size()); } bool operator==(const Constant &that) const { return shape_ == that.shape_ && values_ == that.values_; } bool empty() const; std::size_t size() const; const std::vector &shape() const { return shape_; } std::int64_t LEN() const { return length_; } ScalarValue operator*() const { CHECK(static_cast(values_.size()) == length_); return values_; } // Apply 1-based subscripts ScalarValue At(const std::vector &) const; Constant SHAPE() const; std::ostream &AsFortran(std::ostream &) const; static constexpr DynamicType GetType() { return Result::GetType(); } private: ScalarValue values_; // one contiguous string std::int64_t length_; std::vector shape_; }; using StructureConstructorValues = std::map>>; template<> class Constant : public ConstantBase { public: using Result = SomeDerived; using Base = ConstantBase; Constant(const StructureConstructor &); Constant(StructureConstructor &&); Constant(const semantics::DerivedTypeSpec &, std::vector &&, std::vector &&); Constant(const semantics::DerivedTypeSpec &, std::vector &&, std::vector &&); CLASS_BOILERPLATE(Constant) const semantics::DerivedTypeSpec &derivedTypeSpec() const { return *derivedTypeSpec_; } DynamicType GetType() const { return DynamicType{derivedTypeSpec()}; } private: const semantics::DerivedTypeSpec *derivedTypeSpec_; }; FOR_EACH_LENGTHLESS_INTRINSIC_KIND(extern template class ConstantBase) extern template class ConstantBase; FOR_EACH_INTRINSIC_KIND(extern template class Constant) } #endif // FORTRAN_EVALUATE_CONSTANT_H_