/*
 * 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/SkSLLayout.h"
#include "include/private/SkSLString.h"
#include "include/private/base/SkTFitsIn.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/base/SkMathPriv.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 <cstdint>
#include <limits>
#include <optional>
#include <string_view>
#include <utility>

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 isAllowedInES2() const override {
        return fTargetType.isAllowedInES2();
    }

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

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

    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();
    }

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

    TextureAccess textureAccess() const override {
        return fTargetType.textureAccess();
    }

    SkSpan<const Type* const> 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 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, SkSpan<const Type* const> coercibleTypes)
        : INHERITED(name, "G", kTypeKind) {
        fNumTypes = coercibleTypes.size();
        SkASSERT(fNumTypes <= std::size(fCoercibleTypes));
        std::copy(coercibleTypes.begin(), coercibleTypes.end(), fCoercibleTypes);
    }

    SkSpan<const Type* const> coercibleTypes() const override {
        return SkSpan(fCoercibleTypes, fNumTypes);
    }

private:
    using INHERITED = Type;

    const Type* fCoercibleTypes[9];
    size_t fNumTypes;
};

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();
    }

    double minimumValue() const override {
        return fScalarType.minimumValue();
    }

    double maximumValue() const override {
        return fScalarType.maximumValue();
    }

    bool isScalar() const override {
        return true;
    }

    bool isLiteral() 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;
    }

    using int_limits = std::numeric_limits<int32_t>;
    using short_limits = std::numeric_limits<int16_t>;
    using uint_limits = std::numeric_limits<uint32_t>;
    using ushort_limits = std::numeric_limits<uint16_t>;
    using float_limits = std::numeric_limits<float>;

    /** Returns the maximum value that can fit in the type. */
    double minimumValue() const override {
        switch (this->numberKind()) {
            case NumberKind::kSigned:
                return this->highPrecision() ? int_limits::lowest()
                                             : short_limits::lowest();

            case NumberKind::kUnsigned:
                return 0;

            case NumberKind::kFloat:
            default:
                return float_limits::lowest();
        }
    }

    /** Returns the maximum value that can fit in the type. */
    double maximumValue() const override {
        switch (this->numberKind()) {
            case NumberKind::kSigned:
                return this->highPrecision() ? int_limits::max()
                                             : short_limits::max();

            case NumberKind::kUnsigned:
                return this->highPrecision() ? uint_limits::max()
                                             : ushort_limits::max();

            case NumberKind::kFloat:
            default:
                return float_limits::max();
        }
    }

private:
    using INHERITED = Type;

    NumberKind fNumberKind;
    int8_t fPriority;
    int8_t fBitWidth;
};

class AtomicType final : public Type {
public:
    inline static constexpr TypeKind kTypeKind = TypeKind::kAtomic;

    AtomicType(std::string_view name, const char* abbrev) : INHERITED(name, abbrev, kTypeKind) {}

    bool isAllowedInES2() const override { return false; }

private:
    using INHERITED = Type;
};

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, TextureAccess textureAccess)
        : INHERITED(name, "T", kTypeKind)
        , fDimensions(dimensions)
        , fIsDepth(isDepth)
        , fIsArrayed(isArrayed)
        , fIsMultisampled(isMultisampled)
        , fTextureAccess(textureAccess) {}

    SpvDim_ dimensions() const override {
        return fDimensions;
    }

    bool isDepth() const override {
        return fIsDepth;
    }

    bool isArrayedTexture() const override {
        return fIsArrayed;
    }

    bool isMultisampled() const override {
        return fIsMultisampled;
    }

    TextureAccess textureAccess() const override {
        return fTextureAccess;
    }

private:
    using INHERITED = Type;

    SpvDim_ fDimensions;
    bool fIsDepth;
    bool fIsArrayed;
    bool fIsMultisampled;
    TextureAccess fTextureAccess;
};

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();
    }

    TextureAccess textureAccess() const override {
        return fTextureType.textureAccess();
    }

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 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, SkSpan<const Type* const> types) {
    return std::make_unique<GenericType>(name, 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::MakeAtomicType(std::string_view name, const char* abbrev) {
    return std::make_unique<AtomicType>(name, abbrev);
}

static bool is_too_deeply_nested(const Type* t, int limit) {
    if (limit <= 0) {
        return true;
    }

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

    return false;
}

std::unique_ptr<Type> Type::MakeStructType(const Context& context,
                                           Position pos,
                                           std::string_view name,
                                           std::vector<Field> fields,
                                           bool interfaceBlock) {
    for (const Field& field : fields) {
        if (field.fModifiers.fFlags != Modifiers::kNo_Flag) {
            std::string desc = field.fModifiers.description();
            desc.pop_back();  // remove trailing space
            context.fErrors->error(field.fPosition,
                                   "modifier '" + desc + "' is not permitted on a struct field");
        }
        if (field.fModifiers.fLayout.fFlags & Layout::kBinding_Flag) {
            context.fErrors->error(field.fPosition,
                                   "layout qualifier 'binding' is not permitted on a struct field");
        }
        if (field.fModifiers.fLayout.fFlags & Layout::kSet_Flag) {
            context.fErrors->error(field.fPosition,
                                   "layout qualifier 'set' is not permitted on a struct field");
        }

        if (field.fType->isVoid()) {
            context.fErrors->error(field.fPosition, "type 'void' is not permitted in a struct");
        }
        if (field.fType->isOpaque() && !field.fType->isAtomic()) {
            context.fErrors->error(field.fPosition, "opaque type '" + field.fType->displayName() +
                                                    "' is not permitted in a struct");
        }
    }
    for (const Field& field : fields) {
        if (is_too_deeply_nested(field.fType, kMaxStructDepth)) {
            context.fErrors->error(pos, "struct '" + std::string(name) + "' is too deeply nested");
            break;
        }
    }
    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,
                                            TextureAccess textureAccess) {
    return std::make_unique<TextureType>(name, dimensions, isDepth, isArrayedTexture,
                                         isMultisampled, textureAccess);
}

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) {
        SkSpan<const Type* const> 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::applyQualifiers(const Context& context,
                                  Modifiers* modifiers,
                                  SymbolTable* symbols,
                                  Position pos) const {
    const Type* type;
    type = this->applyPrecisionQualifiers(context, modifiers, symbols, pos);
    type = type->applyAccessQualifiers(context, modifiers, symbols, pos);
    return type;
}

const Type* Type::applyPrecisionQualifiers(const Context& context,
                                           Modifiers* modifiers,
                                           SymbolTable* symbols,
                                           Position pos) const {
    int precisionQualifiers = modifiers->fFlags & (Modifiers::kHighp_Flag |
                                                   Modifiers::kMediump_Flag |
                                                   Modifiers::kLowp_Flag);
    if (!precisionQualifiers) {
        // 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 (SkPopCount(precisionQualifiers) > 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 (precisionQualifiers & Modifiers::kHighp_Flag) {
            // Type is already high precision, and we are requesting high precision. Return as-is.
            return this;
        }

        // SkSL doesn't support low precision, so `lowp` is interpreted as medium precision.
        // 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::applyAccessQualifiers(const Context& context,
                                        Modifiers* modifiers,
                                        SymbolTable* symbols,
                                        Position pos) const {
    int accessQualifiers = modifiers->fFlags & (Modifiers::kReadOnly_Flag |
                                                Modifiers::kWriteOnly_Flag);
    if (!accessQualifiers) {
        // No access qualifiers here. Return the type as-is.
        return this;
    }

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

    if (this->matches(*context.fTypes.fReadWriteTexture2D)) {
        switch (accessQualifiers) {
            case Modifiers::kReadOnly_Flag:
                return context.fTypes.fReadOnlyTexture2D.get();

            case Modifiers::kWriteOnly_Flag:
                return context.fTypes.fWriteOnlyTexture2D.get();

            default:
                context.fErrors->error(pos, "'readonly' and 'writeonly' qualifiers "
                                            "cannot be combined");
                return this;
        }
    }

    context.fErrors->error(pos, "type '" + this->displayName() + "' does not support qualifier '" +
                                Modifiers::DescribeFlags(accessQualifiers) + "'");
    return this;
}

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->find(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: {
            // We are cloning an existing struct, so there's no need to call MakeStructType and
            // fully error-check it again.
            const std::string* name = symbolTable->takeOwnershipOfString(std::string(this->name()));
            return symbolTable->add(std::make_unique<StructType>(
                    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;
}

static bool is_or_contains_array(const Type* type, bool onlyMatchUnsizedArrays) {
    if (type->isStruct()) {
        for (const Type::Field& f : type->fields()) {
            if (is_or_contains_array(f.fType, onlyMatchUnsizedArrays)) {
                return true;
            }
        }
        return false;
    }

    if (type->isArray()) {
        return onlyMatchUnsizedArrays
                    ? (type->isUnsizedArray() || is_or_contains_array(&type->componentType(), true))
                    : true;
    }

    return false;
}

bool Type::isOrContainsArray() const {
    return is_or_contains_array(this, /*onlyMatchUnsizedArrays=*/false);
}

bool Type::isOrContainsUnsizedArray() const {
    return is_or_contains_array(this, /*onlyMatchUnsizedArrays=*/true);
}

bool Type::isOrContainsAtomic() const {
    if (this->isAtomic()) {
        return true;
    }

    if (this->isArray() && this->componentType().isOrContainsAtomic()) {
        return true;
    }

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

    return false;
}

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.isNumber()) {
        // 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->isNumber()) {
       return false;
    }
    if (value >= this->minimumValue() && value <= this->maximumValue()) {
        return false;
    }
    // We found a value that can't fit in our type. Flag it as an error.
    context.fErrors->error(pos, SkSL::String::printf("value is out of range for type '%s': %.0f",
                                                     this->displayName().c_str(),
                                                     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() && !this->isAtomic()) {
        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);
}

std::string Type::Field::description() const {
    return fModifiers.description() + fType->displayName() + " " + std::string(fName) + ";";
}

}  // namespace SkSL
