/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/sksl/ir/SkSLType.h"

#include "include/private/SkSLString.h"
#include "include/private/SkStringView.h"
#include "include/private/SkTFitsIn.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLConstructorArrayCast.h"
#include "src/sksl/ir/SkSLConstructorCompoundCast.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"

#include <algorithm>
#include <cmath>
#include <cstdint>
#include <optional>
#include <string_view>

namespace SkSL {

static constexpr int kMaxStructDepth = 8;

class AliasType final : public Type {
public:
    AliasType(std::string_view name, const Type& targetType)
        : INHERITED(name, targetType.abbreviatedName(), targetType.typeKind())
        , fTargetType(targetType) {}

    const Type& resolve() const override {
        return fTargetType;
    }

    const Type& componentType() const override {
        return fTargetType.componentType();
    }

    NumberKind numberKind() const override {
        return fTargetType.numberKind();
    }

    int priority() const override {
        return fTargetType.priority();
    }

    int columns() const override {
        return fTargetType.columns();
    }

    int rows() const override {
        return fTargetType.rows();
    }

    int bitWidth() const override {
        return fTargetType.bitWidth();
    }

    bool isPrivate() const override {
        return fTargetType.isPrivate();
    }

    bool isAllowedInES2() const override {
        return fTargetType.isAllowedInES2();
    }

    size_t slotCount() const override {
        return fTargetType.slotCount();
    }

    bool isDepth() const override {
        return fTargetType.isDepth();
    }

    bool isArrayedTexture() const override {
        return fTargetType.isArrayedTexture();
    }

    bool isScalar() const override {
        return fTargetType.isScalar();
    }

    bool isLiteral() const override {
        return fTargetType.isLiteral();
    }

    bool isVector() const override {
        return fTargetType.isVector();
    }

    bool isMatrix() const override {
        return fTargetType.isMatrix();
    }

    bool isArray() const override {
        return fTargetType.isArray();
    }

    bool isUnsizedArray() const override {
        return fTargetType.isUnsizedArray();
    }

    bool isStruct() const override {
        return fTargetType.isStruct();
    }

    bool isInterfaceBlock() const override {
        return fTargetType.isInterfaceBlock();
    }

    const std::vector<const Type*>& coercibleTypes() const override {
        return fTargetType.coercibleTypes();
    }

private:
    using INHERITED = Type;

    const Type& fTargetType;
};

class ArrayType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kArray;

    ArrayType(std::string_view name, const char* abbrev, const Type& componentType, int count)
        : INHERITED(name, abbrev, kTypeKind)
        , fComponentType(componentType)
        , fCount(count) {
        SkASSERT(count > 0 || count == kUnsizedArray);
        // Disallow multi-dimensional arrays.
        SkASSERT(!componentType.is<ArrayType>());
    }

    bool isArray() const override {
        return true;
    }

    bool isUnsizedArray() const override {
        return fCount == kUnsizedArray;
    }

    const Type& componentType() const override {
        return fComponentType;
    }

    int columns() const override {
        return fCount;
    }

    int bitWidth() const override {
        return this->componentType().bitWidth();
    }

    bool isPrivate() const override {
        return fComponentType.isPrivate();
    }

    bool isAllowedInES2() const override {
        return fComponentType.isAllowedInES2();
    }

    size_t slotCount() const override {
        SkASSERT(fCount != kUnsizedArray);
        SkASSERT(fCount > 0);
        return fCount * fComponentType.slotCount();
    }

private:
    using INHERITED = Type;

    const Type& fComponentType;
    int fCount;
};

class GenericType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kGeneric;

    GenericType(const char* name, std::vector<const Type*> coercibleTypes)
        : INHERITED(name, "G", kTypeKind)
        , fCoercibleTypes(std::move(coercibleTypes)) {}

    const std::vector<const Type*>& coercibleTypes() const override {
        return fCoercibleTypes;
    }

private:
    using INHERITED = Type;

    std::vector<const Type*> fCoercibleTypes;
};

class LiteralType : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kLiteral;

    LiteralType(const char* name, const Type& scalarType, int8_t priority)
        : INHERITED(name, "L", kTypeKind)
        , fScalarType(scalarType)
        , fPriority(priority) {}

    const Type& scalarTypeForLiteral() const override {
        return fScalarType;
    }

    int priority() const override {
        return fPriority;
    }

    int columns() const override {
        return 1;
    }

    int rows() const override {
        return 1;
    }

    NumberKind numberKind() const override {
        return fScalarType.numberKind();
    }

    int bitWidth() const override {
        return fScalarType.bitWidth();
    }

    bool isScalar() const override {
        return true;
    }

    bool isLiteral() const override {
        return true;
    }

    bool isPrivate() const override {
        return true;
    }

    size_t slotCount() const override {
        return 1;
    }

private:
    using INHERITED = Type;

    const Type& fScalarType;
    int8_t fPriority;
};


class ScalarType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kScalar;

    ScalarType(std::string_view name, const char* abbrev, NumberKind numberKind, int8_t priority,
               int8_t bitWidth)
        : INHERITED(name, abbrev, kTypeKind)
        , fNumberKind(numberKind)
        , fPriority(priority)
        , fBitWidth(bitWidth) {}

    NumberKind numberKind() const override {
        return fNumberKind;
    }

    int priority() const override {
        return fPriority;
    }

    int bitWidth() const override {
        return fBitWidth;
    }

    int columns() const override {
        return 1;
    }

    int rows() const override {
        return 1;
    }

    bool isScalar() const override {
        return true;
    }

    bool isAllowedInES2() const override {
        return fNumberKind != NumberKind::kUnsigned;
    }

    size_t slotCount() const override {
        return 1;
    }

private:
    using INHERITED = Type;

    NumberKind fNumberKind;
    int8_t fPriority;
    int8_t fBitWidth;
};

class MatrixType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kMatrix;

    MatrixType(std::string_view name, const char* abbrev, const Type& componentType,
               int8_t columns, int8_t rows)
        : INHERITED(name, abbrev, kTypeKind)
        , fComponentType(componentType.as<ScalarType>())
        , fColumns(columns)
        , fRows(rows) {
        SkASSERT(columns >= 2 && columns <= 4);
        SkASSERT(rows >= 2 && rows <= 4);
    }

    const ScalarType& componentType() const override {
        return fComponentType;
    }

    int columns() const override {
        return fColumns;
    }

    int rows() const override {
        return fRows;
    }

    int bitWidth() const override {
        return this->componentType().bitWidth();
    }

    bool isMatrix() const override {
        return true;
    }

    bool isAllowedInES2() const override {
        return fColumns == fRows;
    }

    size_t slotCount() const override {
        return fColumns * fRows;
    }

private:
    using INHERITED = Type;

    const ScalarType& fComponentType;
    int8_t fColumns;
    int8_t fRows;
};

class TextureType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kTexture;

    TextureType(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed,
                bool isMultisampled, bool isSampled)
        : INHERITED(name, "T", kTypeKind)
        , fDimensions(dimensions)
        , fIsDepth(isDepth)
        , fIsArrayed(isArrayed)
        , fIsMultisampled(isMultisampled)
        , fIsSampled(isSampled) {}

    SpvDim_ dimensions() const override {
        return fDimensions;
    }

    bool isDepth() const override {
        return fIsDepth;
    }

    bool isArrayedTexture() const override {
        return fIsArrayed;
    }

    bool isMultisampled() const override {
        return fIsMultisampled;
    }

    bool isSampled() const override {
        return fIsSampled;
    }

private:
    using INHERITED = Type;

    SpvDim_ fDimensions;
    bool fIsDepth;
    bool fIsArrayed;
    bool fIsMultisampled;
    bool fIsSampled;
};

class SamplerType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kSampler;

    SamplerType(const char* name, const Type& textureType)
        : INHERITED(name, "Z", kTypeKind)
        , fTextureType(textureType.as<TextureType>()) {}

    const TextureType& textureType() const override {
        return fTextureType;
    }

    SpvDim_ dimensions() const override {
        return fTextureType.dimensions();
    }

    bool isDepth() const override {
        return fTextureType.isDepth();
    }

    bool isArrayedTexture() const override {
        return fTextureType.isArrayedTexture();
    }

    bool isMultisampled() const override {
        return fTextureType.isMultisampled();
    }

    bool isSampled() const override {
        return fTextureType.isSampled();
    }

private:
    using INHERITED = Type;

    const TextureType& fTextureType;
};

class StructType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kStruct;

    StructType(Position pos, std::string_view name, std::vector<Field> fields, bool interfaceBlock)
        : INHERITED(std::move(name), "S", kTypeKind, pos)
        , fFields(std::move(fields))
        , fInterfaceBlock(interfaceBlock) {}

    const std::vector<Field>& fields() const override {
        return fFields;
    }

    bool isStruct() const override {
        return true;
    }

    bool isInterfaceBlock() const override {
        return fInterfaceBlock;
    }

    bool isPrivate() const override {
        return std::any_of(fFields.begin(), fFields.end(), [](const Field& f) {
            return f.fType->isPrivate();
        });
    }

    bool isAllowedInES2() const override {
        return std::all_of(fFields.begin(), fFields.end(), [](const Field& f) {
            return f.fType->isAllowedInES2();
        });
    }

    size_t slotCount() const override {
        size_t slots = 0;
        for (const Field& field : fFields) {
            slots += field.fType->slotCount();
        }
        return slots;
    }

private:
    using INHERITED = Type;

    std::vector<Field> fFields;
    bool fInterfaceBlock;
};

class VectorType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kVector;

    VectorType(std::string_view name, const char* abbrev, const Type& componentType,
               int8_t columns)
        : INHERITED(name, abbrev, kTypeKind)
        , fComponentType(componentType.as<ScalarType>())
        , fColumns(columns) {
        SkASSERT(columns >= 2 && columns <= 4);
    }

    const ScalarType& componentType() const override {
        return fComponentType;
    }

    int columns() const override {
        return fColumns;
    }

    int rows() const override {
        return 1;
    }

    int bitWidth() const override {
        return this->componentType().bitWidth();
    }

    bool isVector() const override {
        return true;
    }

    bool isAllowedInES2() const override {
        return fComponentType.isAllowedInES2();
    }

    size_t slotCount() const override {
        return fColumns;
    }

private:
    using INHERITED = Type;

    const ScalarType& fComponentType;
    int8_t fColumns;
};

std::string Type::getArrayName(int arraySize) const {
    std::string_view name = this->name();
    if (arraySize == kUnsizedArray) {
        return String::printf("%.*s[]", (int)name.size(), name.data());
    }
    return String::printf("%.*s[%d]", (int)name.size(), name.data(), arraySize);
}

std::unique_ptr<Type> Type::MakeAliasType(std::string_view name, const Type& targetType) {
    return std::make_unique<AliasType>(std::move(name), targetType);
}

std::unique_ptr<Type> Type::MakeArrayType(std::string_view name, const Type& componentType,
                                          int columns) {
    return std::make_unique<ArrayType>(std::move(name), componentType.abbreviatedName(),
                                       componentType, columns);
}

std::unique_ptr<Type> Type::MakeGenericType(const char* name, std::vector<const Type*> types) {
    return std::make_unique<GenericType>(name, std::move(types));
}

std::unique_ptr<Type> Type::MakeLiteralType(const char* name, const Type& scalarType,
                                            int8_t priority) {
    return std::make_unique<LiteralType>(name, scalarType, priority);
}

std::unique_ptr<Type> Type::MakeMatrixType(std::string_view name, const char* abbrev,
                                           const Type& componentType, int columns, int8_t rows) {
    return std::make_unique<MatrixType>(name, abbrev, componentType, columns, rows);
}

std::unique_ptr<Type> Type::MakeSamplerType(const char* name, const Type& textureType) {
    return std::make_unique<SamplerType>(name, textureType);
}

std::unique_ptr<Type> Type::MakeSpecialType(const char* name, const char* abbrev,
                                            Type::TypeKind typeKind) {
    return std::unique_ptr<Type>(new Type(name, abbrev, typeKind));
}

std::unique_ptr<Type> Type::MakeScalarType(std::string_view name, const char* abbrev,
                                           Type::NumberKind numberKind, int8_t priority,
                                           int8_t bitWidth) {
    return std::make_unique<ScalarType>(name, abbrev, numberKind, priority, bitWidth);

}

std::unique_ptr<Type> Type::MakeStructType(Position pos, std::string_view name,
                                           std::vector<Field> fields, bool interfaceBlock) {
    return std::make_unique<StructType>(pos, name, std::move(fields), interfaceBlock);
}

std::unique_ptr<Type> Type::MakeTextureType(const char* name, SpvDim_ dimensions, bool isDepth,
                                            bool isArrayedTexture, bool isMultisampled,
                                            bool isSampled) {
    return std::make_unique<TextureType>(name, dimensions, isDepth, isArrayedTexture,
                                         isMultisampled, isSampled);
}

std::unique_ptr<Type> Type::MakeVectorType(std::string_view name, const char* abbrev,
                                           const Type& componentType, int columns) {
    return std::make_unique<VectorType>(name, abbrev, componentType, columns);
}

CoercionCost Type::coercionCost(const Type& other) const {
    if (this->matches(other)) {
        return CoercionCost::Free();
    }
    if (this->typeKind() == other.typeKind() &&
        (this->isVector() || this->isMatrix() || this->isArray())) {
        // Vectors/matrices/arrays of the same size can be coerced if their component type can be.
        if (this->isMatrix() && (this->rows() != other.rows())) {
            return CoercionCost::Impossible();
        }
        if (this->columns() != other.columns()) {
            return CoercionCost::Impossible();
        }
        return this->componentType().coercionCost(other.componentType());
    }
    if (this->isNumber() && other.isNumber()) {
        if (this->isLiteral() && this->isInteger()) {
            return CoercionCost::Free();
        } else if (this->numberKind() != other.numberKind()) {
            return CoercionCost::Impossible();
        } else if (other.priority() >= this->priority()) {
            return CoercionCost::Normal(other.priority() - this->priority());
        } else {
            return CoercionCost::Narrowing(this->priority() - other.priority());
        }
    }
    if (fTypeKind == TypeKind::kGeneric) {
        const std::vector<const Type*>& types = this->coercibleTypes();
        for (size_t i = 0; i < types.size(); i++) {
            if (types[i]->matches(other)) {
                return CoercionCost::Normal((int) i + 1);
            }
        }
    }
    return CoercionCost::Impossible();
}

const Type* Type::applyPrecisionQualifiers(const Context& context,
                                           Modifiers* modifiers,
                                           SymbolTable* symbols,
                                           Position pos) const {
    // SkSL doesn't support low precision, so `lowp` is interpreted as medium precision.
    bool highp   = modifiers->fFlags & Modifiers::kHighp_Flag;
    bool mediump = modifiers->fFlags & Modifiers::kMediump_Flag;
    bool lowp    = modifiers->fFlags & Modifiers::kLowp_Flag;

    if (!lowp && !mediump && !highp) {
        // No precision qualifiers here. Return the type as-is.
        return this;
    }

    if (!ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
        // We want to discourage precision modifiers internally. Instead, use the type that
        // corresponds to the precision you need. (e.g. half vs float, short vs int)
        context.fErrors->error(pos, "precision qualifiers are not allowed");
        return context.fTypes.fPoison.get();
    }

    if ((int(lowp) + int(mediump) + int(highp)) != 1) {
        context.fErrors->error(pos, "only one precision qualifier can be used");
        return context.fTypes.fPoison.get();
    }

    // We're going to return a whole new type, so the modifier bits can be cleared out.
    modifiers->fFlags &= ~(Modifiers::kHighp_Flag |
                           Modifiers::kMediump_Flag |
                           Modifiers::kLowp_Flag);

    const Type& component = this->componentType();
    if (component.highPrecision()) {
        if (highp) {
            // Type is already high precision, and we are requesting high precision. Return as-is.
            return this;
        }

        // Ascertain the mediump equivalent type for this type, if any.
        const Type* mediumpType;
        switch (component.numberKind()) {
            case Type::NumberKind::kFloat:
                mediumpType = context.fTypes.fHalf.get();
                break;

            case Type::NumberKind::kSigned:
                mediumpType = context.fTypes.fShort.get();
                break;

            case Type::NumberKind::kUnsigned:
                mediumpType = context.fTypes.fUShort.get();
                break;

            default:
                mediumpType = context.fTypes.fPoison.get();
                break;
        }

        if (mediumpType) {
            // Convert the mediump component type into the final vector/matrix/array type as needed.
            return this->isArray()
                           ? symbols->addArrayDimension(mediumpType, this->columns())
                           : &mediumpType->toCompound(context, this->columns(), this->rows());
        }
    }

    context.fErrors->error(pos, "type '" + this->displayName() +
                                 "' does not support precision qualifiers");
    return context.fTypes.fPoison.get();
}

const Type& Type::toCompound(const Context& context, int columns, int rows) const {
    SkASSERT(this->isScalar());
    if (columns == 1 && rows == 1) {
        return *this;
    }
    if (this->matches(*context.fTypes.fFloat) || this->matches(*context.fTypes.fFloatLiteral)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fFloat;
                    case 2: return *context.fTypes.fFloat2;
                    case 3: return *context.fTypes.fFloat3;
                    case 4: return *context.fTypes.fFloat4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            case 2:
                switch (columns) {
                    case 2: return *context.fTypes.fFloat2x2;
                    case 3: return *context.fTypes.fFloat3x2;
                    case 4: return *context.fTypes.fFloat4x2;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            case 3:
                switch (columns) {
                    case 2: return *context.fTypes.fFloat2x3;
                    case 3: return *context.fTypes.fFloat3x3;
                    case 4: return *context.fTypes.fFloat4x3;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            case 4:
                switch (columns) {
                    case 2: return *context.fTypes.fFloat2x4;
                    case 3: return *context.fTypes.fFloat3x4;
                    case 4: return *context.fTypes.fFloat4x4;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fHalf)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fHalf;
                    case 2: return *context.fTypes.fHalf2;
                    case 3: return *context.fTypes.fHalf3;
                    case 4: return *context.fTypes.fHalf4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            case 2:
                switch (columns) {
                    case 2: return *context.fTypes.fHalf2x2;
                    case 3: return *context.fTypes.fHalf3x2;
                    case 4: return *context.fTypes.fHalf4x2;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            case 3:
                switch (columns) {
                    case 2: return *context.fTypes.fHalf2x3;
                    case 3: return *context.fTypes.fHalf3x3;
                    case 4: return *context.fTypes.fHalf4x3;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            case 4:
                switch (columns) {
                    case 2: return *context.fTypes.fHalf2x4;
                    case 3: return *context.fTypes.fHalf3x4;
                    case 4: return *context.fTypes.fHalf4x4;
                    default: SK_ABORT("unsupported matrix column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fInt) || this->matches(*context.fTypes.fIntLiteral)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fInt;
                    case 2: return *context.fTypes.fInt2;
                    case 3: return *context.fTypes.fInt3;
                    case 4: return *context.fTypes.fInt4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fShort)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fShort;
                    case 2: return *context.fTypes.fShort2;
                    case 3: return *context.fTypes.fShort3;
                    case 4: return *context.fTypes.fShort4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fUInt)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fUInt;
                    case 2: return *context.fTypes.fUInt2;
                    case 3: return *context.fTypes.fUInt3;
                    case 4: return *context.fTypes.fUInt4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fUShort)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fUShort;
                    case 2: return *context.fTypes.fUShort2;
                    case 3: return *context.fTypes.fUShort3;
                    case 4: return *context.fTypes.fUShort4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    } else if (this->matches(*context.fTypes.fBool)) {
        switch (rows) {
            case 1:
                switch (columns) {
                    case 1: return *context.fTypes.fBool;
                    case 2: return *context.fTypes.fBool2;
                    case 3: return *context.fTypes.fBool3;
                    case 4: return *context.fTypes.fBool4;
                    default: SK_ABORT("unsupported vector column count (%d)", columns);
                }
            default: SK_ABORT("unsupported row count (%d)", rows);
        }
    }
    SkDEBUGFAILF("unsupported toCompound type %s", this->description().c_str());
    return *context.fTypes.fVoid;
}

const Type* Type::clone(SymbolTable* symbolTable) const {
    // Many types are built-ins, and exist in every SymbolTable by default.
    if (this->isInBuiltinTypes()) {
        return this;
    }
    // Even if the type isn't a built-in, it might already exist in the SymbolTable.
    const Symbol* clonedSymbol = (*symbolTable)[this->name()];
    if (clonedSymbol != nullptr) {
        const Type& clonedType = clonedSymbol->as<Type>();
        SkASSERT(clonedType.typeKind() == this->typeKind());
        return &clonedType;
    }
    // This type actually needs to be cloned into the destination SymbolTable.
    switch (this->typeKind()) {
        case TypeKind::kArray: {
            return symbolTable->addArrayDimension(&this->componentType(), this->columns());
        }
        case TypeKind::kStruct: {
            const std::string* name = symbolTable->takeOwnershipOfString(std::string(this->name()));
            return symbolTable->add(Type::MakeStructType(
                    this->fPosition, *name, this->fields(), this->isInterfaceBlock()));
        }
        default:
            SkDEBUGFAILF("don't know how to clone type '%s'", this->description().c_str());
            return nullptr;
    }
}

std::unique_ptr<Expression> Type::coerceExpression(std::unique_ptr<Expression> expr,
                                                   const Context& context) const {
    if (!expr || expr->isIncomplete(context)) {
        return nullptr;
    }
    if (expr->type().matches(*this)) {
        return expr;
    }

    const Position pos = expr->fPosition;
    const ProgramSettings& settings = context.fConfig->fSettings;
    if (!expr->coercionCost(*this).isPossible(settings.fAllowNarrowingConversions)) {
        context.fErrors->error(pos, "expected '" + this->displayName() + "', but found '" +
                expr->type().displayName() + "'");
        return nullptr;
    }

    if (this->isScalar()) {
        return ConstructorScalarCast::Make(context, pos, *this, std::move(expr));
    }
    if (this->isVector() || this->isMatrix()) {
        return ConstructorCompoundCast::Make(context, pos, *this, std::move(expr));
    }
    if (this->isArray()) {
        return ConstructorArrayCast::Make(context, pos, *this, std::move(expr));
    }
    context.fErrors->error(pos, "cannot construct '" + this->displayName() + "'");
    return nullptr;
}

bool Type::isPrivate() const {
    return skstd::starts_with(this->name(), '$');
}

bool Type::isOrContainsArray() const {
    if (this->isStruct()) {
        for (const Field& f : this->fields()) {
            if (f.fType->isOrContainsArray()) {
                return true;
            }
        }
        return false;
    }

    return this->isArray();
}

bool Type::isTooDeeplyNested(int limit) const {
    if (limit < 0) {
        return true;
    }

    if (this->isStruct()) {
        for (const Type::Field& f : this->fields()) {
            if (f.fType->isTooDeeplyNested(limit - 1)) {
                return true;
            }
        }
    }

    return false;
}

bool Type::isTooDeeplyNested() const {
    return this->isTooDeeplyNested(kMaxStructDepth);
}

bool Type::isAllowedInES2(const Context& context) const {
    return !context.fConfig->strictES2Mode() || this->isAllowedInES2();
}

bool Type::checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const {
    bool foundError = false;
    const Type& baseType = this->componentType();
    if (baseType.isInteger()) {
        // Replace constant expressions with their corresponding values.
        const Expression* valueExpr = ConstantFolder::GetConstantValueForVariable(expr);
        if (valueExpr->supportsConstantValues()) {
            // Iterate over every constant subexpression in the value.
            int numSlots = valueExpr->type().slotCount();
            for (int slot = 0; slot < numSlots; ++slot) {
                std::optional<double> slotVal = valueExpr->getConstantValue(slot);
                // Check for Literal values that are out of range for the base type.
                if (slotVal.has_value() &&
                    baseType.checkForOutOfRangeLiteral(context, *slotVal, valueExpr->fPosition)) {
                    foundError = true;
                }
            }
        }
    }

    // We don't need range checks for floats or booleans; any matched-type value is acceptable.
    return foundError;
}

bool Type::checkForOutOfRangeLiteral(const Context& context, double value, Position pos) const {
    SkASSERT(this->isScalar());
    if (!this->isInteger()) {
        return false;
    }
    if (value >= this->minimumValue() && value <= this->maximumValue()) {
        return false;
    }
    // We found a value that can't fit in our integral type. Flag it as an error.
    context.fErrors->error(pos, SkSL::String::printf("integer is out of range for type '%s': %.0f",
                                                     this->displayName().c_str(),
                                                     std::floor(value)));
    return true;
}

bool Type::checkIfUsableInArray(const Context& context, Position arrayPos) const {
    if (this->isArray()) {
        context.fErrors->error(arrayPos, "multi-dimensional arrays are not supported");
        return false;
    }
    if (this->isVoid()) {
        context.fErrors->error(arrayPos, "type 'void' may not be used in an array");
        return false;
    }
    if (this->isOpaque()) {
        context.fErrors->error(arrayPos, "opaque type '" + std::string(this->name()) +
                                         "' may not be used in an array");
        return false;
    }
    return true;
}

SKSL_INT Type::convertArraySize(const Context& context, Position arrayPos,
        std::unique_ptr<Expression> size) const {
    size = context.fTypes.fInt->coerceExpression(std::move(size), context);
    if (!size) {
        return 0;
    }
    if (!this->checkIfUsableInArray(context, arrayPos)) {
        return 0;
    }
    SKSL_INT count;
    if (!ConstantFolder::GetConstantInt(*size, &count)) {
        context.fErrors->error(size->fPosition, "array size must be an integer");
        return 0;
    }
    if (count <= 0) {
        context.fErrors->error(size->fPosition, "array size must be positive");
        return 0;
    }
    if (!SkTFitsIn<int32_t>(count)) {
        context.fErrors->error(size->fPosition, "array size is too large");
        return 0;
    }
    return static_cast<int>(count);
}

}  // namespace SkSL
