/*
 * 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/SkSLSymbolTable.h"

#include "include/core/SkSpan.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLUnresolvedFunction.h"

namespace SkSL {

static SkSpan<const FunctionDeclaration* const> get_overload_set(
        const Symbol& s,
        const FunctionDeclaration*& scratchPtr) {
    switch (s.kind()) {
        case Symbol::Kind::kFunctionDeclaration:
            scratchPtr = &s.as<FunctionDeclaration>();
            return SkSpan(&scratchPtr, 1);

        case Symbol::Kind::kUnresolvedFunction:
            return SkSpan(s.as<UnresolvedFunction>().functions());

        default:
            return SkSpan<const FunctionDeclaration* const>{};
    }
}

const Symbol* SymbolTable::operator[](std::string_view name) {
    return this->lookup(fBuiltin ? nullptr : this, MakeSymbolKey(name));
}

const Symbol* SymbolTable::lookup(SymbolTable* writableSymbolTable, const SymbolKey& key) {
    // Symbol-table lookup can cause new UnresolvedFunction nodes to be created; however, we don't
    // want these to end up in built-in root symbol tables (where they will outlive the Program
    // associated with those UnresolvedFunction nodes). `writableSymbolTable` tracks the closest
    // symbol table to the root which is not a built-in.
    if (!fBuiltin) {
        writableSymbolTable = this;
    }
    const Symbol** symbolPPtr = fSymbols.find(key);
    if (!symbolPPtr) {
        // The symbol wasn't found; recurse into the parent symbol table.
        return fParent ? fParent->lookup(writableSymbolTable, key)
                       : nullptr;
    }

    const Symbol* symbol = *symbolPPtr;
    if (!fParent) {
        // We found a symbol at the top level.
        return symbol;
    }

    const FunctionDeclaration* scratchPtr;
    SkSpan<const FunctionDeclaration* const> overloadSet = get_overload_set(*symbol, scratchPtr);
    if (overloadSet.empty()) {
        // We found a non-function-related symbol. Return it.
        return symbol;
    }

    // We found a function-related symbol. We need to return the complete overload set.
    return this->buildOverloadSet(writableSymbolTable, key, symbol, overloadSet);
}

const Symbol* SymbolTable::buildOverloadSet(SymbolTable* writableSymbolTable,
                                            const SymbolKey& key,
                                            const Symbol* symbol,
                                            SkSpan<const FunctionDeclaration* const> overloadSet) {
    // Scan the parent symbol table for a matching symbol.
    const Symbol* overloadedSymbol = fParent->lookup(writableSymbolTable, key);
    if (!overloadedSymbol) {
        return symbol;
    }

    const FunctionDeclaration* scratchPtr;
    SkSpan<const FunctionDeclaration* const> parentOverloadSet = get_overload_set(*overloadedSymbol,
                                                                                  scratchPtr);
    if (parentOverloadSet.empty()) {
        // The parent symbol wasn't function-related. Return the symbol we found.
        return symbol;
    }

    // We've found two distinct overload sets; we need to combine them. Start with the initial set.
    std::vector<const FunctionDeclaration*> combinedOverloadSet{overloadSet.begin(),
                                                                overloadSet.end()};
    // Now combine in any unique overloads from the parent overload set.
    for (const FunctionDeclaration* prev : parentOverloadSet) {
        bool matchFound = false;
        for (const FunctionDeclaration* current : combinedOverloadSet) {
            if (current->matches(*prev)) {
                matchFound = true;
                break;
            }
        }
        if (!matchFound) {
            combinedOverloadSet.push_back(prev);
        }
    }

    SkASSERT(combinedOverloadSet.size() >= overloadSet.size());
    if (combinedOverloadSet.size() == overloadSet.size()) {
        // We didn't add anything to the overload set. Our existing symbol is fine.
        return symbol;
    }

    // Add this combined overload set to the symbol table.
    SkASSERT(combinedOverloadSet.size() > 1);
    return writableSymbolTable
                   ? writableSymbolTable->takeOwnershipOfSymbol(
                             std::make_unique<UnresolvedFunction>(std::move(combinedOverloadSet)))
                   : nullptr;
}

const std::string* SymbolTable::takeOwnershipOfString(std::string str) {
    fOwnedStrings.push_front(std::move(str));
    // Because fOwnedStrings is a linked list, pointers to elements are stable.
    return &fOwnedStrings.front();
}

void SymbolTable::addWithoutOwnership(const Symbol* symbol) {
    const std::string_view& name = symbol->name();

    const Symbol*& refInSymbolTable = fSymbols[MakeSymbolKey(name)];
    if (refInSymbolTable == nullptr) {
        refInSymbolTable = symbol;
        return;
    }

    if (!symbol->is<FunctionDeclaration>()) {
        fContext.fErrors->error(symbol->fPosition, "symbol '" + std::string(name) +
                "' was already defined");
        return;
    }

    std::vector<const FunctionDeclaration*> functions;
    if (refInSymbolTable->is<FunctionDeclaration>()) {
        functions = {&refInSymbolTable->as<FunctionDeclaration>(),
                     &symbol->as<FunctionDeclaration>()};

        refInSymbolTable = this->takeOwnershipOfSymbol(
                std::make_unique<UnresolvedFunction>(std::move(functions)));
    } else if (refInSymbolTable->is<UnresolvedFunction>()) {
        functions = refInSymbolTable->as<UnresolvedFunction>().functions();
        functions.push_back(&symbol->as<FunctionDeclaration>());

        refInSymbolTable = this->takeOwnershipOfSymbol(
                std::make_unique<UnresolvedFunction>(std::move(functions)));
    }
}

const Type* SymbolTable::addArrayDimension(const Type* type, int arraySize) {
    if (arraySize == 0) {
        return type;
    }
    // If this is a builtin type, we add it to the topmost non-builtin symbol table to enable
    // additional reuse of the array-type.
    if (type->isInBuiltinTypes() && fParent && !fParent->fBuiltin) {
        return fParent->addArrayDimension(type, arraySize);
    }
    // Reuse an existing array type with this name if one already exists in our symbol table.
    std::string arrayName = type->getArrayName(arraySize);
    if (const Symbol* existingType = (*this)[arrayName]) {
        return &existingType->as<Type>();
    }
    // Add a new array type to the symbol table.
    const std::string* arrayNamePtr = this->takeOwnershipOfString(std::move(arrayName));
    return this->add(Type::MakeArrayType(*arrayNamePtr, *type, arraySize));
}

}  // namespace SkSL
