//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FunctionLookup.cpp: Used for storing function calls that have not yet been resolved during
// parsing.
//

#include "compiler/translator/FunctionLookup.h"

#include "compiler/translator/ImmutableStringBuilder.h"
#include "nb/cpp14oncpp11.h"

namespace sh
{

namespace
{

const char kFunctionMangledNameSeparator = '(';

CONSTEXPR const ImmutableString kEmptyName("");

// Helper function for GetMangledNames
// Gets all ordered combinations of elements in list[currentIndex, end]
std::vector<std::vector<int>> GetImplicitConversionCombinations(const std::vector<int> &list)
{
    std::vector<std::vector<int>> target;
    target.push_back(std::vector<int>());

    for (size_t currentIndex = 0; currentIndex < list.size(); currentIndex++)
    {
        size_t prevIterSize = target.size();
        for (size_t copyIndex = 0; copyIndex < prevIterSize; copyIndex++)
        {
            std::vector<int> combination = target[copyIndex];
            combination.push_back(list[currentIndex]);
            target.push_back(combination);
        }
    }

    return target;
}

}  // anonymous namespace

TFunctionLookup::TFunctionLookup(const ImmutableString &name,
                                 const TType *constructorType,
                                 const TSymbol *symbol)
    : mName(name), mConstructorType(constructorType), mThisNode(nullptr), mSymbol(symbol)
{}

// static
TFunctionLookup *TFunctionLookup::CreateConstructor(const TType *type)
{
    ASSERT(type != nullptr);
    return new TFunctionLookup(kEmptyName, type, nullptr);
}

// static
TFunctionLookup *TFunctionLookup::CreateFunctionCall(const ImmutableString &name,
                                                     const TSymbol *symbol)
{
    ASSERT(name != "");
    return new TFunctionLookup(name, nullptr, symbol);
}

const ImmutableString &TFunctionLookup::name() const
{
    return mName;
}

ImmutableString TFunctionLookup::getMangledName() const
{
    return GetMangledName(mName.data(), mArguments);
}

ImmutableString TFunctionLookup::GetMangledName(const char *functionName,
                                                const TIntermSequence &arguments)
{
    std::string newName(functionName);
    newName += kFunctionMangledNameSeparator;

    for (TIntermNode *argument : arguments)
    {
        newName += argument->getAsTyped()->getType().getMangledName();
    }
    return ImmutableString(newName);
}

std::vector<ImmutableString> GetMangledNames(const char *functionName,
                                             const TIntermSequence &arguments)
{
    std::vector<ImmutableString> target;

    std::vector<int> indexes;
    for (int i = 0; i < static_cast<int>(arguments.size()); i++)
    {
        TIntermNode *argument = arguments[i];
        TBasicType argType    = argument->getAsTyped()->getType().getBasicType();
        if (argType == EbtInt || argType == EbtUInt)
        {
            indexes.push_back(i);
        }
    }

    std::vector<std::vector<int>> combinations = GetImplicitConversionCombinations(indexes);
    for (const std::vector<int> &combination : combinations)
    {
        // combination: ordered list of indexes for arguments that should be converted to float
        std::string newName(functionName);
        newName += kFunctionMangledNameSeparator;
        // combination[currentIndex] represents index of next argument to be converted
        int currentIndex = 0;
        for (int i = 0; i < (int)arguments.size(); i++)
        {
            TIntermNode *argument = arguments[i];

            if (currentIndex != static_cast<int>(combination.size()) &&
                combination[currentIndex] == i)
            {
                // Convert
                TType type = argument->getAsTyped()->getType();
                type.setBasicType(EbtFloat);
                newName += type.getMangledName();
                currentIndex++;
            }
            else
            {
                // Don't convert
                newName += argument->getAsTyped()->getType().getMangledName();
            }
        }
        target.push_back(ImmutableString(newName));
    }

    return target;
}

std::vector<ImmutableString> TFunctionLookup::getMangledNamesForImplicitConversions() const
{
    return GetMangledNames(mName.data(), mArguments);
}

bool TFunctionLookup::isConstructor() const
{
    return mConstructorType != nullptr;
}

const TType &TFunctionLookup::constructorType() const
{
    return *mConstructorType;
}

void TFunctionLookup::setThisNode(TIntermTyped *thisNode)
{
    mThisNode = thisNode;
}

TIntermTyped *TFunctionLookup::thisNode() const
{
    return mThisNode;
}

void TFunctionLookup::addArgument(TIntermTyped *argument)
{
    mArguments.push_back(argument);
}

TIntermSequence &TFunctionLookup::arguments()
{
    return mArguments;
}

const TSymbol *TFunctionLookup::symbol() const
{
    return mSymbol;
}

}  // namespace sh
