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

#ifndef SKSL_FUNCTIONDECLARATION
#define SKSL_FUNCTIONDECLARATION

#include "include/private/SkSLModifiers.h"
#include "include/private/SkSLProgramKind.h"
#include "include/private/SkSLSymbol.h"
#include "include/private/SkTArray.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVariable.h"

namespace SkSL {

class FunctionDefinition;

/**
 * A function declaration (not a definition -- does not contain a body).
 */
class FunctionDeclaration final : public Symbol {
public:
    static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration;

    FunctionDeclaration(int offset, const Modifiers* modifiers, StringFragment name,
                        std::vector<const Variable*> parameters, const Type* returnType,
                        bool builtin)
    : INHERITED(offset, kSymbolKind, name, /*type=*/nullptr)
    , fDefinition(nullptr)
    , fModifiers(modifiers)
    , fParameters(std::move(parameters))
    , fReturnType(returnType)
    , fBuiltin(builtin)
    , fIsMain(name == "main") {}

    static const FunctionDeclaration* Convert(const Context& context,
                                              SymbolTable& symbols,
                                              ModifiersPool& modifiersPool,
                                              int offset,
                                              const Modifiers* modifiers,
                                              StringFragment name,
                                              std::vector<std::unique_ptr<Variable>> parameters,
                                              const Type* returnType,
                                              bool isBuiltin);

    const Modifiers& modifiers() const {
        return *fModifiers;
    }

    const FunctionDefinition* definition() const {
        return fDefinition;
    }

    void setDefinition(const FunctionDefinition* definition) const {
        fDefinition = definition;
    }

    const std::vector<const Variable*>& parameters() const {
        return fParameters;
    }

    const Type& returnType() const {
        return *fReturnType;
    }

    bool isBuiltin() const {
        return fBuiltin;
    }

    bool isMain() const {
        return fIsMain;
    }

    String mangledName() const {
        if ((this->isBuiltin() && !this->definition()) || this->isMain()) {
            // Builtins without a definition (like `sin` or `sqrt`) must use their real names.
            return this->name();
        }
        // GLSL forbids two underscores in a row; add an extra character if necessary to avoid this.
        const char* splitter = this->name().endsWith("_") ? "x_" : "_";
        // Rename function to `funcname_returntypeparamtypes`.
        String result = this->name() + splitter + this->returnType().abbreviatedName();
        for (const Variable* p : this->parameters()) {
            result += p->type().abbreviatedName();
        }
        return result;
    }

    String description() const override {
        String result = this->returnType().displayName() + " " + this->name() + "(";
        String separator;
        for (const Variable* p : this->parameters()) {
            result += separator;
            separator = ", ";
            result += p->type().displayName();
            result += " ";
            result += p->name();
        }
        result += ")";
        return result;
    }

    bool matches(const FunctionDeclaration& f) const {
        if (this->name() != f.name()) {
            return false;
        }
        const std::vector<const Variable*>& parameters = this->parameters();
        const std::vector<const Variable*>& otherParameters = f.parameters();
        if (parameters.size() != otherParameters.size()) {
            return false;
        }
        for (size_t i = 0; i < parameters.size(); i++) {
            if (parameters[i]->type() != otherParameters[i]->type()) {
                return false;
            }
        }
        return true;
    }

    /**
     * Determine the effective types of this function's parameters and return value when called with
     * the given arguments. This is relevant for functions with generic parameter types, where this
     * will collapse the generic types down into specific concrete types.
     *
     * Returns true if it was able to select a concrete set of types for the generic function, false
     * if there is no possible way this can match the argument types. Note that even a true return
     * does not guarantee that the function can be successfully called with those arguments, merely
     * indicates that an attempt should be made. If false is returned, the state of
     * outParameterTypes and outReturnType are undefined.
     *
     * This always assumes narrowing conversions are *allowed*. The calling code needs to verify
     * that each argument can actually be coerced to the final parameter type, respecting the
     * narrowing-conversions flag. This is handled in callCost(), or in convertCall() (via coerce).
     */
    using ParamTypes = SkSTArray<8, const Type*>;
    bool determineFinalTypes(const ExpressionArray& arguments,
                             ParamTypes* outParameterTypes, const Type** outReturnType) const {
        const std::vector<const Variable*>& parameters = this->parameters();
        SkASSERT(arguments.size() == parameters.size());

        outParameterTypes->reserve_back(arguments.size());
        int genericIndex = -1;
        for (size_t i = 0; i < arguments.size(); i++) {
            // Non-generic parameters are final as-is.
            const Type& parameterType = parameters[i]->type();
            if (parameterType.typeKind() != Type::TypeKind::kGeneric) {
                outParameterTypes->push_back(&parameterType);
                continue;
            }
            // We use the first generic parameter we find to lock in the generic index;
            // e.g. if we find `float3` here, all `$genType`s will be assumed to be `float3`.
            const std::vector<const Type*>& types = parameterType.coercibleTypes();
            if (genericIndex == -1) {
                for (size_t j = 0; j < types.size(); j++) {
                    if (arguments[i]->type().canCoerceTo(*types[j], /*allowNarrowing=*/true)) {
                        genericIndex = j;
                        break;
                    }
                }
                if (genericIndex == -1) {
                    // The passed-in type wasn't a match for ANY of the generic possibilities.
                    // This function isn't a match at all.
                    return false;
                }
            }
            outParameterTypes->push_back(types[genericIndex]);
        }
        // Apply the generic index to our return type.
        const Type& returnType = this->returnType();
        if (returnType.typeKind() == Type::TypeKind::kGeneric) {
            if (genericIndex == -1) {
                // We don't support functions with a generic return type and no other generics.
                return false;
            }
            *outReturnType = returnType.coercibleTypes()[genericIndex];
        } else {
            *outReturnType = &returnType;
        }
        return true;
    }

private:
    mutable const FunctionDefinition* fDefinition;
    const Modifiers* fModifiers;
    std::vector<const Variable*> fParameters;
    const Type* fReturnType;
    bool fBuiltin;
    bool fIsMain;

    friend class SkSL::dsl::DSLFunction;

    using INHERITED = Symbol;
};

}  // namespace SkSL

#endif
