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

#include "include/sksl/SkSLOperator.h"

#include "include/core/SkTypes.h"
#include "include/private/SkStringView.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLType.h"

#include <memory>
#include <utility>

namespace SkSL {

Operator::Precedence Operator::getBinaryPrecedence() const {
    switch (this->kind()) {
        case Kind::STAR:         // fall through
        case Kind::SLASH:        // fall through
        case Kind::PERCENT:      return Precedence::kMultiplicative;
        case Kind::PLUS:         // fall through
        case Kind::MINUS:        return Precedence::kAdditive;
        case Kind::SHL:          // fall through
        case Kind::SHR:          return Precedence::kShift;
        case Kind::LT:           // fall through
        case Kind::GT:           // fall through
        case Kind::LTEQ:         // fall through
        case Kind::GTEQ:         return Precedence::kRelational;
        case Kind::EQEQ:         // fall through
        case Kind::NEQ:          return Precedence::kEquality;
        case Kind::BITWISEAND:   return Precedence::kBitwiseAnd;
        case Kind::BITWISEXOR:   return Precedence::kBitwiseXor;
        case Kind::BITWISEOR:    return Precedence::kBitwiseOr;
        case Kind::LOGICALAND:   return Precedence::kLogicalAnd;
        case Kind::LOGICALXOR:   return Precedence::kLogicalXor;
        case Kind::LOGICALOR:    return Precedence::kLogicalOr;
        case Kind::EQ:           // fall through
        case Kind::PLUSEQ:       // fall through
        case Kind::MINUSEQ:      // fall through
        case Kind::STAREQ:       // fall through
        case Kind::SLASHEQ:      // fall through
        case Kind::PERCENTEQ:    // fall through
        case Kind::SHLEQ:        // fall through
        case Kind::SHREQ:        // fall through
        case Kind::BITWISEANDEQ: // fall through
        case Kind::BITWISEXOREQ: // fall through
        case Kind::BITWISEOREQ:  return Precedence::kAssignment;
        case Kind::COMMA:        return Precedence::kSequence;
        default: SK_ABORT("unsupported binary operator");
    }
}

const char* Operator::operatorName() const {
    switch (this->kind()) {
        case Kind::PLUS:         return " + ";
        case Kind::MINUS:        return " - ";
        case Kind::STAR:         return " * ";
        case Kind::SLASH:        return " / ";
        case Kind::PERCENT:      return " % ";
        case Kind::SHL:          return " << ";
        case Kind::SHR:          return " >> ";
        case Kind::LOGICALNOT:   return "!";
        case Kind::LOGICALAND:   return " && ";
        case Kind::LOGICALOR:    return " || ";
        case Kind::LOGICALXOR:   return " ^^ ";
        case Kind::BITWISENOT:   return "~";
        case Kind::BITWISEAND:   return " & ";
        case Kind::BITWISEOR:    return " | ";
        case Kind::BITWISEXOR:   return " ^ ";
        case Kind::EQ:           return " = ";
        case Kind::EQEQ:         return " == ";
        case Kind::NEQ:          return " != ";
        case Kind::LT:           return " < ";
        case Kind::GT:           return " > ";
        case Kind::LTEQ:         return " <= ";
        case Kind::GTEQ:         return " >= ";
        case Kind::PLUSEQ:       return " += ";
        case Kind::MINUSEQ:      return " -= ";
        case Kind::STAREQ:       return " *= ";
        case Kind::SLASHEQ:      return " /= ";
        case Kind::PERCENTEQ:    return " %= ";
        case Kind::SHLEQ:        return " <<= ";
        case Kind::SHREQ:        return " >>= ";
        case Kind::BITWISEANDEQ: return " &= ";
        case Kind::BITWISEOREQ:  return " |= ";
        case Kind::BITWISEXOREQ: return " ^= ";
        case Kind::PLUSPLUS:     return "++";
        case Kind::MINUSMINUS:   return "--";
        case Kind::COMMA:        return ", ";
        default: SkUNREACHABLE;
    }
}

std::string_view Operator::tightOperatorName() const {
    std::string_view name = this->operatorName();
    if (skstd::starts_with(name, ' ')) {
        name.remove_prefix(1);
    }
    if (skstd::ends_with(name, ' ')) {
        name.remove_suffix(1);
    }
    return name;
}

bool Operator::isAssignment() const {
    switch (this->kind()) {
        case Kind::EQ:           // fall through
        case Kind::PLUSEQ:       // fall through
        case Kind::MINUSEQ:      // fall through
        case Kind::STAREQ:       // fall through
        case Kind::SLASHEQ:      // fall through
        case Kind::PERCENTEQ:    // fall through
        case Kind::SHLEQ:        // fall through
        case Kind::SHREQ:        // fall through
        case Kind::BITWISEOREQ:  // fall through
        case Kind::BITWISEXOREQ: // fall through
        case Kind::BITWISEANDEQ:
            return true;
        default:
            return false;
    }
}

Operator Operator::removeAssignment() const {
    switch (this->kind()) {
        case Kind::PLUSEQ:       return Kind::PLUS;
        case Kind::MINUSEQ:      return Kind::MINUS;
        case Kind::STAREQ:       return Kind::STAR;
        case Kind::SLASHEQ:      return Kind::SLASH;
        case Kind::PERCENTEQ:    return Kind::PERCENT;
        case Kind::SHLEQ:        return Kind::SHL;
        case Kind::SHREQ:        return Kind::SHR;
        case Kind::BITWISEOREQ:  return Kind::BITWISEOR;
        case Kind::BITWISEXOREQ: return Kind::BITWISEXOR;
        case Kind::BITWISEANDEQ: return Kind::BITWISEAND;
        default: return *this;
    }
}

bool Operator::isRelational() const {
    switch (this->kind()) {
        case Kind::LT:
        case Kind::GT:
        case Kind::LTEQ:
        case Kind::GTEQ:
            return true;
        default:
            return false;
    }
}

bool Operator::isOnlyValidForIntegralTypes() const {
    switch (this->kind()) {
        case Kind::SHL:
        case Kind::SHR:
        case Kind::BITWISEAND:
        case Kind::BITWISEOR:
        case Kind::BITWISEXOR:
        case Kind::PERCENT:
        case Kind::SHLEQ:
        case Kind::SHREQ:
        case Kind::BITWISEANDEQ:
        case Kind::BITWISEOREQ:
        case Kind::BITWISEXOREQ:
        case Kind::PERCENTEQ:
            return true;
        default:
            return false;
    }
}

bool Operator::isValidForMatrixOrVector() const {
    switch (this->kind()) {
        case Kind::PLUS:
        case Kind::MINUS:
        case Kind::STAR:
        case Kind::SLASH:
        case Kind::PERCENT:
        case Kind::SHL:
        case Kind::SHR:
        case Kind::BITWISEAND:
        case Kind::BITWISEOR:
        case Kind::BITWISEXOR:
        case Kind::PLUSEQ:
        case Kind::MINUSEQ:
        case Kind::STAREQ:
        case Kind::SLASHEQ:
        case Kind::PERCENTEQ:
        case Kind::SHLEQ:
        case Kind::SHREQ:
        case Kind::BITWISEANDEQ:
        case Kind::BITWISEOREQ:
        case Kind::BITWISEXOREQ:
            return true;
        default:
            return false;
    }
}

bool Operator::isMatrixMultiply(const Type& left, const Type& right) const {
    if (this->kind() != Kind::STAR && this->kind() != Kind::STAREQ) {
        return false;
    }
    if (left.isMatrix()) {
        return right.isMatrix() || right.isVector();
    }
    return left.isVector() && right.isMatrix();
}

/**
 * Determines the operand and result types of a binary expression. Returns true if the expression is
 * legal, false otherwise. If false, the values of the out parameters are undefined.
 */
bool Operator::determineBinaryType(const Context& context,
                                   const Type& left,
                                   const Type& right,
                                   const Type** outLeftType,
                                   const Type** outRightType,
                                   const Type** outResultType) const {
    const bool allowNarrowing = context.fConfig->fSettings.fAllowNarrowingConversions;
    switch (this->kind()) {
        case Kind::EQ:  // left = right
            if (left.isVoid()) {
                return false;
            }
            *outLeftType = &left;
            *outRightType = &left;
            *outResultType = &left;
            return right.canCoerceTo(left, allowNarrowing);

        case Kind::EQEQ:   // left == right
        case Kind::NEQ: {  // left != right
            if (left.isVoid() || left.isOpaque()) {
                return false;
            }
            CoercionCost rightToLeft = right.coercionCost(left),
                         leftToRight = left.coercionCost(right);
            if (rightToLeft < leftToRight) {
                if (rightToLeft.isPossible(allowNarrowing)) {
                    *outLeftType = &left;
                    *outRightType = &left;
                    *outResultType = context.fTypes.fBool.get();
                    return true;
                }
            } else {
                if (leftToRight.isPossible(allowNarrowing)) {
                    *outLeftType = &right;
                    *outRightType = &right;
                    *outResultType = context.fTypes.fBool.get();
                    return true;
                }
            }
            return false;
        }
        case Kind::LOGICALOR:   // left || right
        case Kind::LOGICALAND:  // left && right
        case Kind::LOGICALXOR:  // left ^^ right
            *outLeftType = context.fTypes.fBool.get();
            *outRightType = context.fTypes.fBool.get();
            *outResultType = context.fTypes.fBool.get();
            return left.canCoerceTo(*context.fTypes.fBool, allowNarrowing) &&
                   right.canCoerceTo(*context.fTypes.fBool, allowNarrowing);

        case Operator::Kind::COMMA:  // left, right
            if (left.isOpaque() || right.isOpaque()) {
                return false;
            }
            *outLeftType = &left;
            *outRightType = &right;
            *outResultType = &right;
            return true;

        default:
            break;
    }

    // Boolean types only support the operators listed above (, = == != || && ^^).
    // If we've gotten this far with a boolean, we have an unsupported operator.
    const Type& leftComponentType = left.componentType();
    const Type& rightComponentType = right.componentType();
    if (leftComponentType.isBoolean() || rightComponentType.isBoolean()) {
        return false;
    }

    bool isAssignment = this->isAssignment();
    if (this->isMatrixMultiply(left, right)) {  // left * right
        // Determine final component type.
        if (!this->determineBinaryType(context, left.componentType(), right.componentType(),
                                       outLeftType, outRightType, outResultType)) {
            return false;
        }
        // Convert component type to compound.
        *outLeftType = &(*outResultType)->toCompound(context, left.columns(), left.rows());
        *outRightType = &(*outResultType)->toCompound(context, right.columns(), right.rows());
        int leftColumns = left.columns(), leftRows = left.rows();
        int rightColumns = right.columns(), rightRows = right.rows();
        if (right.isVector()) {
            // `matrix * vector` treats the vector as a column vector; we need to transpose it.
            std::swap(rightColumns, rightRows);
            SkASSERT(rightColumns == 1);
        }
        if (rightColumns > 1) {
            *outResultType = &(*outResultType)->toCompound(context, rightColumns, leftRows);
        } else {
            // The result was a column vector. Transpose it back to a row.
            *outResultType = &(*outResultType)->toCompound(context, leftRows, rightColumns);
        }
        if (isAssignment && ((*outResultType)->columns() != leftColumns ||
                             (*outResultType)->rows() != leftRows)) {
            return false;
        }
        return leftColumns == rightRows;
    }

    bool leftIsVectorOrMatrix = left.isVector() || left.isMatrix();
    bool validMatrixOrVectorOp = this->isValidForMatrixOrVector();

    if (leftIsVectorOrMatrix && validMatrixOrVectorOp && right.isScalar()) {
        // Determine final component type.
        if (!this->determineBinaryType(context, left.componentType(), right,
                                       outLeftType, outRightType, outResultType)) {
            return false;
        }
        // Convert component type to compound.
        *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
        if (!this->isRelational()) {
            *outResultType = &(*outResultType)->toCompound(context, left.columns(), left.rows());
        }
        return true;
    }

    bool rightIsVectorOrMatrix = right.isVector() || right.isMatrix();

    if (!isAssignment && rightIsVectorOrMatrix && validMatrixOrVectorOp && left.isScalar()) {
        // Determine final component type.
        if (!this->determineBinaryType(context, left, right.componentType(),
                                       outLeftType, outRightType, outResultType)) {
            return false;
        }
        // Convert component type to compound.
        *outRightType = &(*outRightType)->toCompound(context, right.columns(), right.rows());
        if (!this->isRelational()) {
            *outResultType = &(*outResultType)->toCompound(context, right.columns(), right.rows());
        }
        return true;
    }

    CoercionCost rightToLeftCost = right.coercionCost(left);
    CoercionCost leftToRightCost = isAssignment ? CoercionCost::Impossible()
                                                : left.coercionCost(right);

    if ((left.isScalar() && right.isScalar()) || (leftIsVectorOrMatrix && validMatrixOrVectorOp)) {
        if (this->isOnlyValidForIntegralTypes()) {
            if (!leftComponentType.isInteger() || !rightComponentType.isInteger()) {
                return false;
            }
        }
        if (rightToLeftCost.isPossible(allowNarrowing) && rightToLeftCost < leftToRightCost) {
            // Right-to-Left conversion is possible and cheaper
            *outLeftType = &left;
            *outRightType = &left;
            *outResultType = &left;
        } else if (leftToRightCost.isPossible(allowNarrowing)) {
            // Left-to-Right conversion is possible (and at least as cheap as Right-to-Left)
            *outLeftType = &right;
            *outRightType = &right;
            *outResultType = &right;
        } else {
            return false;
        }
        if (this->isRelational()) {
            *outResultType = context.fTypes.fBool.get();
        }
        return true;
    }
    return false;
}

}  // namespace SkSL
