//===-- ConvertType.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "flang/Lower/ConvertType.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/CallInterface.h"
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Support/Utils.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "flang-lower-type"

using Fortran::common::VectorElementCategory;

//===--------------------------------------------------------------------===//
// Intrinsic type translation helpers
//===--------------------------------------------------------------------===//

static mlir::Type genRealType(mlir::MLIRContext *context, int kind) {
  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
          Fortran::common::TypeCategory::Real, kind)) {
    switch (kind) {
    case 2:
      return mlir::FloatType::getF16(context);
    case 3:
      return mlir::FloatType::getBF16(context);
    case 4:
      return mlir::FloatType::getF32(context);
    case 8:
      return mlir::FloatType::getF64(context);
    case 10:
      return mlir::FloatType::getF80(context);
    case 16:
      return mlir::FloatType::getF128(context);
    }
  }
  llvm_unreachable("REAL type translation not implemented");
}

template <int KIND>
int getIntegerBits() {
  return Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,
                                 KIND>::Scalar::bits;
}
static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind,
                                 bool isUnsigned = false) {
  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
          Fortran::common::TypeCategory::Integer, kind)) {
    mlir::IntegerType::SignednessSemantics signedness =
        (isUnsigned ? mlir::IntegerType::SignednessSemantics::Unsigned
                    : mlir::IntegerType::SignednessSemantics::Signless);

    switch (kind) {
    case 1:
      return mlir::IntegerType::get(context, getIntegerBits<1>(), signedness);
    case 2:
      return mlir::IntegerType::get(context, getIntegerBits<2>(), signedness);
    case 4:
      return mlir::IntegerType::get(context, getIntegerBits<4>(), signedness);
    case 8:
      return mlir::IntegerType::get(context, getIntegerBits<8>(), signedness);
    case 16:
      return mlir::IntegerType::get(context, getIntegerBits<16>(), signedness);
    }
  }
  llvm_unreachable("INTEGER kind not translated");
}

static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) {
  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
          Fortran::common::TypeCategory::Logical, KIND))
    return fir::LogicalType::get(context, KIND);
  return {};
}

static mlir::Type genCharacterType(
    mlir::MLIRContext *context, int KIND,
    Fortran::lower::LenParameterTy len = fir::CharacterType::unknownLen()) {
  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
          Fortran::common::TypeCategory::Character, KIND))
    return fir::CharacterType::get(context, KIND, len);
  return {};
}

static mlir::Type genComplexType(mlir::MLIRContext *context, int KIND) {
  if (Fortran::evaluate::IsValidKindOfIntrinsicType(
          Fortran::common::TypeCategory::Complex, KIND))
    return fir::ComplexType::get(context, KIND);
  return {};
}

static mlir::Type
genFIRType(mlir::MLIRContext *context, Fortran::common::TypeCategory tc,
           int kind,
           llvm::ArrayRef<Fortran::lower::LenParameterTy> lenParameters) {
  switch (tc) {
  case Fortran::common::TypeCategory::Real:
    return genRealType(context, kind);
  case Fortran::common::TypeCategory::Integer:
    return genIntegerType(context, kind);
  case Fortran::common::TypeCategory::Complex:
    return genComplexType(context, kind);
  case Fortran::common::TypeCategory::Logical:
    return genLogicalType(context, kind);
  case Fortran::common::TypeCategory::Character:
    if (!lenParameters.empty())
      return genCharacterType(context, kind, lenParameters[0]);
    return genCharacterType(context, kind);
  default:
    break;
  }
  llvm_unreachable("unhandled type category");
}

//===--------------------------------------------------------------------===//
// Symbol and expression type translation
//===--------------------------------------------------------------------===//

/// TypeBuilderImpl translates expression and symbol type taking into account
/// their shape and length parameters. For symbols, attributes such as
/// ALLOCATABLE or POINTER are reflected in the fir type.
/// It uses evaluate::DynamicType and evaluate::Shape when possible to
/// avoid re-implementing type/shape analysis here.
/// Do not use the FirOpBuilder from the AbstractConverter to get fir/mlir types
/// since it is not guaranteed to exist yet when we lower types.
namespace {
struct TypeBuilderImpl {

  TypeBuilderImpl(Fortran::lower::AbstractConverter &converter)
      : derivedTypeInConstruction{converter.getTypeConstructionStack()},
        converter{converter}, context{&converter.getMLIRContext()} {}

  template <typename A>
  mlir::Type genExprType(const A &expr) {
    std::optional<Fortran::evaluate::DynamicType> dynamicType = expr.GetType();
    if (!dynamicType)
      return genTypelessExprType(expr);
    Fortran::common::TypeCategory category = dynamicType->category();

    mlir::Type baseType;
    bool isPolymorphic = (dynamicType->IsPolymorphic() ||
                          dynamicType->IsUnlimitedPolymorphic()) &&
                         !dynamicType->IsAssumedType();
    if (dynamicType->IsUnlimitedPolymorphic()) {
      baseType = mlir::NoneType::get(context);
    } else if (category == Fortran::common::TypeCategory::Derived) {
      baseType = genDerivedType(dynamicType->GetDerivedTypeSpec());
    } else {
      // LOGICAL, INTEGER, REAL, COMPLEX, CHARACTER
      llvm::SmallVector<Fortran::lower::LenParameterTy> params;
      translateLenParameters(params, category, expr);
      baseType = genFIRType(context, category, dynamicType->kind(), params);
    }
    std::optional<Fortran::evaluate::Shape> shapeExpr =
        Fortran::evaluate::GetShape(converter.getFoldingContext(), expr);
    fir::SequenceType::Shape shape;
    if (shapeExpr) {
      translateShape(shape, std::move(*shapeExpr));
    } else {
      // Shape static analysis cannot return something useful for the shape.
      // Use unknown extents.
      int rank = expr.Rank();
      if (rank < 0)
        TODO(converter.getCurrentLocation(), "assumed rank expression types");
      for (int dim = 0; dim < rank; ++dim)
        shape.emplace_back(fir::SequenceType::getUnknownExtent());
    }

    if (!shape.empty()) {
      if (isPolymorphic)
        return fir::ClassType::get(fir::SequenceType::get(shape, baseType));
      return fir::SequenceType::get(shape, baseType);
    }
    if (isPolymorphic)
      return fir::ClassType::get(baseType);
    return baseType;
  }

  template <typename A>
  void translateShape(A &shape, Fortran::evaluate::Shape &&shapeExpr) {
    for (Fortran::evaluate::MaybeExtentExpr extentExpr : shapeExpr) {
      fir::SequenceType::Extent extent = fir::SequenceType::getUnknownExtent();
      if (std::optional<std::int64_t> constantExtent =
              toInt64(std::move(extentExpr)))
        extent = *constantExtent;
      shape.push_back(extent);
    }
  }

  template <typename A>
  std::optional<std::int64_t> toInt64(A &&expr) {
    return Fortran::evaluate::ToInt64(Fortran::evaluate::Fold(
        converter.getFoldingContext(), std::move(expr)));
  }

  template <typename A>
  mlir::Type genTypelessExprType(const A &expr) {
    fir::emitFatalError(converter.getCurrentLocation(), "not a typeless expr");
  }

  mlir::Type genTypelessExprType(const Fortran::lower::SomeExpr &expr) {
    return std::visit(
        Fortran::common::visitors{
            [&](const Fortran::evaluate::BOZLiteralConstant &) -> mlir::Type {
              return mlir::NoneType::get(context);
            },
            [&](const Fortran::evaluate::NullPointer &) -> mlir::Type {
              return fir::ReferenceType::get(mlir::NoneType::get(context));
            },
            [&](const Fortran::evaluate::ProcedureDesignator &proc)
                -> mlir::Type {
              return Fortran::lower::translateSignature(proc, converter);
            },
            [&](const Fortran::evaluate::ProcedureRef &) -> mlir::Type {
              return mlir::NoneType::get(context);
            },
            [](const auto &x) -> mlir::Type {
              using T = std::decay_t<decltype(x)>;
              static_assert(!Fortran::common::HasMember<
                                T, Fortran::evaluate::TypelessExpression>,
                            "missing typeless expr handling");
              llvm::report_fatal_error("not a typeless expression");
            },
        },
        expr.u);
  }

  mlir::Type genSymbolType(const Fortran::semantics::Symbol &symbol,
                           bool isAlloc = false, bool isPtr = false) {
    mlir::Location loc = converter.genLocation(symbol.name());
    mlir::Type ty;
    // If the symbol is not the same as the ultimate one (i.e, it is host or use
    // associated), all the symbol properties are the ones of the ultimate
    // symbol but the volatile and asynchronous attributes that may differ. To
    // avoid issues with helper functions that would not follow association
    // links, the fir type is built based on the ultimate symbol. This relies
    // on the fact volatile and asynchronous are not reflected in fir types.
    const Fortran::semantics::Symbol &ultimate = symbol.GetUltimate();

    if (Fortran::semantics::IsProcedurePointer(ultimate)) {
      Fortran::evaluate::ProcedureDesignator proc(ultimate);
      auto procTy{Fortran::lower::translateSignature(proc, converter)};
      return fir::BoxProcType::get(context, procTy);
    }

    if (const Fortran::semantics::DeclTypeSpec *type = ultimate.GetType()) {
      if (const Fortran::semantics::IntrinsicTypeSpec *tySpec =
              type->AsIntrinsic()) {
        int kind = toInt64(Fortran::common::Clone(tySpec->kind())).value();
        llvm::SmallVector<Fortran::lower::LenParameterTy> params;
        translateLenParameters(params, tySpec->category(), ultimate);
        ty = genFIRType(context, tySpec->category(), kind, params);
      } else if (type->IsUnlimitedPolymorphic()) {
        ty = mlir::NoneType::get(context);
      } else if (const Fortran::semantics::DerivedTypeSpec *tySpec =
                     type->AsDerived()) {
        ty = genDerivedType(*tySpec);
      } else {
        fir::emitFatalError(loc, "symbol's type must have a type spec");
      }
    } else {
      fir::emitFatalError(loc, "symbol must have a type");
    }
    bool isPolymorphic = (Fortran::semantics::IsPolymorphic(symbol) ||
                          Fortran::semantics::IsUnlimitedPolymorphic(symbol)) &&
                         !Fortran::semantics::IsAssumedType(symbol);
    if (ultimate.IsObjectArray()) {
      auto shapeExpr =
          Fortran::evaluate::GetShape(converter.getFoldingContext(), ultimate);
      if (!shapeExpr)
        TODO(loc, "assumed rank symbol type");
      fir::SequenceType::Shape shape;
      translateShape(shape, std::move(*shapeExpr));
      ty = fir::SequenceType::get(shape, ty);
    }
    if (Fortran::semantics::IsPointer(symbol))
      return fir::wrapInClassOrBoxType(fir::PointerType::get(ty),
                                       isPolymorphic);
    if (Fortran::semantics::IsAllocatable(symbol))
      return fir::wrapInClassOrBoxType(fir::HeapType::get(ty), isPolymorphic);
    // isPtr and isAlloc are variable that were promoted to be on the
    // heap or to be pointers, but they do not have Fortran allocatable
    // or pointer semantics, so do not use box for them.
    if (isPtr)
      return fir::PointerType::get(ty);
    if (isAlloc)
      return fir::HeapType::get(ty);
    if (isPolymorphic)
      return fir::ClassType::get(ty);
    return ty;
  }

  /// Does \p component has non deferred lower bounds that are not compile time
  /// constant 1.
  static bool componentHasNonDefaultLowerBounds(
      const Fortran::semantics::Symbol &component) {
    if (const auto *objDetails =
            component.detailsIf<Fortran::semantics::ObjectEntityDetails>())
      for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape())
        if (auto lb = bounds.lbound().GetExplicit())
          if (auto constant = Fortran::evaluate::ToInt64(*lb))
            if (!constant || *constant != 1)
              return true;
    return false;
  }

  mlir::Type genVectorType(const Fortran::semantics::DerivedTypeSpec &tySpec) {
    assert(tySpec.scope() && "Missing scope for Vector type");
    auto vectorSize{tySpec.scope()->size()};
    switch (tySpec.category()) {
      SWITCH_COVERS_ALL_CASES
    case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector): {
      int64_t vecElemKind;
      int64_t vecElemCategory;

      for (const auto &pair : tySpec.parameters()) {
        if (pair.first == "element_category") {
          vecElemCategory =
              Fortran::evaluate::ToInt64(pair.second.GetExplicit())
                  .value_or(-1);
        } else if (pair.first == "element_kind") {
          vecElemKind =
              Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(0);
        }
      }

      assert((vecElemCategory >= 0 &&
              static_cast<size_t>(vecElemCategory) <
                  Fortran::common::VectorElementCategory_enumSize) &&
             "Vector element type is not specified");
      assert(vecElemKind && "Vector element kind is not specified");

      int64_t numOfElements = vectorSize / vecElemKind;
      switch (static_cast<VectorElementCategory>(vecElemCategory)) {
        SWITCH_COVERS_ALL_CASES
      case VectorElementCategory::Integer:
        return fir::VectorType::get(numOfElements,
                                    genIntegerType(context, vecElemKind));
      case VectorElementCategory::Unsigned:
        return fir::VectorType::get(numOfElements,
                                    genIntegerType(context, vecElemKind, true));
      case VectorElementCategory::Real:
        return fir::VectorType::get(numOfElements,
                                    genRealType(context, vecElemKind));
      }
      break;
    }
    case (Fortran::semantics::DerivedTypeSpec::Category::PairVector):
    case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector):
      return fir::VectorType::get(vectorSize * 8,
                                  mlir::IntegerType::get(context, 1));
    case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType):
      Fortran::common::die("Vector element type not implemented");
    }
  }

  mlir::Type genDerivedType(const Fortran::semantics::DerivedTypeSpec &tySpec) {
    std::vector<std::pair<std::string, mlir::Type>> ps;
    std::vector<std::pair<std::string, mlir::Type>> cs;
    if (tySpec.IsVectorType()) {
      return genVectorType(tySpec);
    }

    const Fortran::semantics::Symbol &typeSymbol = tySpec.typeSymbol();
    const Fortran::semantics::Scope &derivedScope = DEREF(tySpec.GetScope());
    if (mlir::Type ty = getTypeIfDerivedAlreadyInConstruction(derivedScope))
      return ty;

    auto rec = fir::RecordType::get(context, converter.mangleName(tySpec));
    // Maintain the stack of types for recursive references and to speed-up
    // the derived type constructions that can be expensive for derived type
    // with dozens of components/parents (modern Fortran).
    derivedTypeInConstruction.try_emplace(&derivedScope, rec);

    // Gather the record type fields.
    // (1) The data components.
    if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
      // In HLFIR the parent component is the first fir.type component.
      for (const auto &componentName :
           typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
               .componentNames()) {
        auto scopeIter = derivedScope.find(componentName);
        assert(scopeIter != derivedScope.cend() &&
               "failed to find derived type component symbol");
        const Fortran::semantics::Symbol &component = scopeIter->second.get();
        mlir::Type ty = genSymbolType(component);
        cs.emplace_back(converter.getRecordTypeFieldName(component), ty);
      }
    } else {
      for (const auto &component :
           Fortran::semantics::OrderedComponentIterator(tySpec)) {
        // In the lowering to FIR the parent component does not appear in the
        // fir.type and its components are inlined at the beginning of the
        // fir.type<>.
        // FIXME: this strategy leads to bugs because padding should be inserted
        // after the component of the parents so that the next components do not
        // end-up in the parent storage if the sum of the parent's component
        // storage size is not a multiple of the parent type storage alignment.

        // Lowering is assuming non deferred component lower bounds are
        // always 1. Catch any situations where this is not true for now.
        if (componentHasNonDefaultLowerBounds(component))
          TODO(converter.genLocation(component.name()),
               "derived type components with non default lower bounds");
        if (IsProcedure(component))
          TODO(converter.genLocation(component.name()), "procedure components");
        mlir::Type ty = genSymbolType(component);
        // Do not add the parent component (component of the parents are
        // added and should be sufficient, the parent component would
        // duplicate the fields). Note that genSymbolType must be called above
        // on it so that the dispatch table for the parent type still gets
        // emitted as needed.
        if (component.test(Fortran::semantics::Symbol::Flag::ParentComp))
          continue;
        cs.emplace_back(converter.getRecordTypeFieldName(component), ty);
      }
    }

    mlir::Location loc = converter.genLocation(typeSymbol.name());
    // (2) The LEN type parameters.
    for (const auto &param :
         Fortran::semantics::OrderParameterDeclarations(typeSymbol))
      if (param->get<Fortran::semantics::TypeParamDetails>().attr() ==
          Fortran::common::TypeParamAttr::Len) {
        TODO(loc, "parameterized derived types");
        // TODO: emplace in ps. Beware that param is the symbol in the type
        // declaration, not instantiation: its kind may not be a constant.
        // The instantiated symbol in tySpec.scope should be used instead.
        ps.emplace_back(param->name().ToString(), genSymbolType(*param));
      }

    rec.finalize(ps, cs);

    if (!ps.empty()) {
      // TODO: this type is a PDT (parametric derived type) with length
      // parameter. Create the functions to use for allocation, dereferencing,
      // and address arithmetic here.
    }
    LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec << '\n');

    // Generate the type descriptor object if any
    if (const Fortran::semantics::Symbol *typeInfoSym =
            derivedScope.runtimeDerivedTypeDescription())
      converter.registerTypeInfo(loc, *typeInfoSym, tySpec, rec);
    return rec;
  }

  // To get the character length from a symbol, make an fold a designator for
  // the symbol to cover the case where the symbol is an assumed length named
  // constant and its length comes from its init expression length.
  template <int Kind>
  fir::SequenceType::Extent
  getCharacterLengthHelper(const Fortran::semantics::Symbol &symbol) {
    using TC =
        Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, Kind>;
    auto designator = Fortran::evaluate::Fold(
        converter.getFoldingContext(),
        Fortran::evaluate::Expr<TC>{Fortran::evaluate::Designator<TC>{symbol}});
    if (auto len = toInt64(std::move(designator.LEN())))
      return *len;
    return fir::SequenceType::getUnknownExtent();
  }

  template <typename T>
  void translateLenParameters(
      llvm::SmallVectorImpl<Fortran::lower::LenParameterTy> &params,
      Fortran::common::TypeCategory category, const T &exprOrSym) {
    if (category == Fortran::common::TypeCategory::Character)
      params.push_back(getCharacterLength(exprOrSym));
    else if (category == Fortran::common::TypeCategory::Derived)
      TODO(converter.getCurrentLocation(), "derived type length parameters");
  }
  Fortran::lower::LenParameterTy
  getCharacterLength(const Fortran::semantics::Symbol &symbol) {
    const Fortran::semantics::DeclTypeSpec *type = symbol.GetType();
    if (!type ||
        type->category() != Fortran::semantics::DeclTypeSpec::Character ||
        !type->AsIntrinsic())
      llvm::report_fatal_error("not a character symbol");
    int kind =
        toInt64(Fortran::common::Clone(type->AsIntrinsic()->kind())).value();
    switch (kind) {
    case 1:
      return getCharacterLengthHelper<1>(symbol);
    case 2:
      return getCharacterLengthHelper<2>(symbol);
    case 4:
      return getCharacterLengthHelper<4>(symbol);
    }
    llvm_unreachable("unknown character kind");
  }

  template <typename A>
  Fortran::lower::LenParameterTy getCharacterLength(const A &expr) {
    return fir::SequenceType::getUnknownExtent();
  }

  template <typename T>
  Fortran::lower::LenParameterTy
  getCharacterLength(const Fortran::evaluate::FunctionRef<T> &funcRef) {
    if (auto constantLen = toInt64(funcRef.LEN()))
      return *constantLen;
    return fir::SequenceType::getUnknownExtent();
  }

  Fortran::lower::LenParameterTy
  getCharacterLength(const Fortran::lower::SomeExpr &expr) {
    // Do not use dynamic type length here. We would miss constant
    // lengths opportunities because dynamic type only has the length
    // if it comes from a declaration.
    if (const auto *charExpr = std::get_if<
            Fortran::evaluate::Expr<Fortran::evaluate::SomeCharacter>>(
            &expr.u)) {
      if (auto constantLen = toInt64(charExpr->LEN()))
        return *constantLen;
    } else if (auto dynamicType = expr.GetType()) {
      // When generating derived type type descriptor as structure constructor,
      // semantics wraps designators to data component initialization into
      // CLASS(*), regardless of their actual type.
      // GetType() will recover the actual symbol type as the dynamic type, so
      // getCharacterLength may be reached even if expr is packaged as an
      // Expr<SomeDerived> instead of an Expr<SomeChar>.
      // Just use the dynamic type here again to retrieve the length.
      if (auto constantLen = toInt64(dynamicType->GetCharLength()))
        return *constantLen;
    }
    return fir::SequenceType::getUnknownExtent();
  }

  mlir::Type genVariableType(const Fortran::lower::pft::Variable &var) {
    return genSymbolType(var.getSymbol(), var.isHeapAlloc(), var.isPointer());
  }

  /// Derived type can be recursive. That is, pointer components of a derived
  /// type `t` have type `t`. This helper returns `t` if it is already being
  /// lowered to avoid infinite loops.
  mlir::Type getTypeIfDerivedAlreadyInConstruction(
      const Fortran::semantics::Scope &derivedScope) const {
    return derivedTypeInConstruction.lookup(&derivedScope);
  }

  /// Stack derived type being processed to avoid infinite loops in case of
  /// recursive derived types. The depth of derived types is expected to be
  /// shallow (<10), so a SmallVector is sufficient.
  Fortran::lower::TypeConstructionStack &derivedTypeInConstruction;
  Fortran::lower::AbstractConverter &converter;
  mlir::MLIRContext *context;
};
} // namespace

mlir::Type Fortran::lower::getFIRType(mlir::MLIRContext *context,
                                      Fortran::common::TypeCategory tc,
                                      int kind,
                                      llvm::ArrayRef<LenParameterTy> params) {
  return genFIRType(context, tc, kind, params);
}

mlir::Type Fortran::lower::translateDerivedTypeToFIRType(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::semantics::DerivedTypeSpec &tySpec) {
  return TypeBuilderImpl{converter}.genDerivedType(tySpec);
}

mlir::Type Fortran::lower::translateSomeExprToFIRType(
    Fortran::lower::AbstractConverter &converter, const SomeExpr &expr) {
  return TypeBuilderImpl{converter}.genExprType(expr);
}

mlir::Type Fortran::lower::translateSymbolToFIRType(
    Fortran::lower::AbstractConverter &converter, const SymbolRef symbol) {
  return TypeBuilderImpl{converter}.genSymbolType(symbol);
}

mlir::Type Fortran::lower::translateVariableToFIRType(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::pft::Variable &var) {
  return TypeBuilderImpl{converter}.genVariableType(var);
}

mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) {
  return genRealType(context, kind);
}

bool Fortran::lower::isDerivedTypeWithLenParameters(
    const Fortran::semantics::Symbol &sym) {
  if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType())
    if (const Fortran::semantics::DerivedTypeSpec *derived =
            declTy->AsDerived())
      return Fortran::semantics::CountLenParameters(*derived) > 0;
  return false;
}

template <typename T>
mlir::Type Fortran::lower::TypeBuilder<T>::genType(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::evaluate::FunctionRef<T> &funcRef) {
  return TypeBuilderImpl{converter}.genExprType(funcRef);
}

const Fortran::semantics::DerivedTypeSpec &
Fortran::lower::ComponentReverseIterator::advanceToParentType() {
  const Fortran::semantics::Scope *scope = currentParentType->GetScope();
  auto parentComp =
      DEREF(scope).find(currentTypeDetails->GetParentComponentName().value());
  assert(parentComp != scope->cend() && "failed to get parent component");
  setCurrentType(parentComp->second->GetType()->derivedTypeSpec());
  return *currentParentType;
}

void Fortran::lower::ComponentReverseIterator::setCurrentType(
    const Fortran::semantics::DerivedTypeSpec &derived) {
  currentParentType = &derived;
  currentTypeDetails = &currentParentType->typeSymbol()
                            .get<Fortran::semantics::DerivedTypeDetails>();
  componentIt = currentTypeDetails->componentNames().crbegin();
  componentItEnd = currentTypeDetails->componentNames().crend();
}

using namespace Fortran::evaluate;
using namespace Fortran::common;
FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder, )
