/*
 * 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_SYMBOLTABLE
#define SKSL_SYMBOLTABLE

#include "include/core/SkTypes.h"
#include "include/private/SkOpts_spi.h"
#include "include/private/SkSLSymbol.h"
#include "include/private/SkTHash.h"

#include <cstddef>
#include <cstdint>
#include <forward_list>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

template <typename T> class SkSpan;

namespace SkSL {

class Context;
class FunctionDeclaration;
class Type;

/**
 * Maps identifiers to symbols. Functions, in particular, are mapped to either FunctionDeclaration
 * or UnresolvedFunction depending on whether they are overloaded or not.
 */
class SymbolTable {
public:
    SymbolTable(const Context& context, bool builtin)
    : fBuiltin(builtin)
    , fContext(context) {}

    SymbolTable(std::shared_ptr<SymbolTable> parent, bool builtin)
    : fParent(parent)
    , fBuiltin(builtin)
    , fContext(parent->fContext) {}

    /** Replaces the passed-in SymbolTable with a newly-created child symbol table. */
    static void Push(std::shared_ptr<SymbolTable>* table) {
        Push(table, (*table)->isBuiltin());
    }
    static void Push(std::shared_ptr<SymbolTable>* table, bool isBuiltin) {
        *table = std::make_shared<SymbolTable>(*table, isBuiltin);
    }

    /**
     * Replaces the passed-in SymbolTable with its parent. If the child symbol table is otherwise
     * unreferenced, it will be deleted.
     */
    static void Pop(std::shared_ptr<SymbolTable>* table) {
        *table = (*table)->fParent;
    }

    /**
     * If the input is a built-in symbol table, returns a new empty symbol table as a child of the
     * input table. If the input is not a built-in symbol table, returns it as-is. Built-in symbol
     * tables must not be mutated after creation, so they must be wrapped if mutation is necessary.
     */
    static std::shared_ptr<SymbolTable> WrapIfBuiltin(std::shared_ptr<SymbolTable> symbolTable) {
        if (!symbolTable) {
            return nullptr;
        }
        if (!symbolTable->isBuiltin()) {
            return symbolTable;
        }
        return std::make_shared<SymbolTable>(std::move(symbolTable), /*builtin=*/false);
    }

    /**
     * Looks up the requested symbol and returns it. If a function has overloads, an
     * UnresolvedFunction symbol (pointing to all of the candidates) will be added to the symbol
     * table and returned.
     */
    const Symbol* operator[](std::string_view name);

    /**
     * Returns true if the name refers to a type (user or built-in) in the current symbol table.
     */
    bool isType(std::string_view name) const;

    /**
     * Returns true if the name refers to a builtin type.
     */
    bool isBuiltinType(std::string_view name) const;

    /**
     * Adds a symbol to this symbol table, without conferring ownership. The caller is responsible
     * for keeping the Symbol alive throughout the lifetime of the program/module.
     */
    void addWithoutOwnership(const Symbol* symbol);

    template <typename T>
    const T* add(std::unique_ptr<T> symbol) {
        const T* ptr = symbol.get();
        this->addWithoutOwnership(ptr);
        this->takeOwnershipOfSymbol(std::move(symbol));
        return ptr;
    }

    template <typename T>
    const T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
        const T* ptr = symbol.get();
        fOwnedSymbols.push_back(std::move(symbol));
        return ptr;
    }

    /**
     * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol
     * table. The created array type is returned. If zero is passed, the base type is returned
     * unchanged.
     */
    const Type* addArrayDimension(const Type* type, int arraySize);

    // Call fn for every symbol in the table.  You may not mutate anything.
    template <typename Fn>
    void foreach(Fn&& fn) const {
        fSymbols.foreach(
                [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); });
    }

    size_t count() {
        return fSymbols.count();
    }

    /** Returns true if this is a built-in SymbolTable. */
    bool isBuiltin() const {
        return fBuiltin;
    }

    const std::string* takeOwnershipOfString(std::string n);

    /**
     * Indicates that this symbol table's parent is in a different module than this one.
     */
    void markModuleBoundary() {
        fAtModuleBoundary = true;
    }

    std::shared_ptr<SymbolTable> fParent;

    std::vector<std::unique_ptr<const Symbol>> fOwnedSymbols;

private:
    struct SymbolKey {
        std::string_view fName;
        uint32_t         fHash;

        bool operator==(const SymbolKey& that) const { return fName == that.fName; }
        bool operator!=(const SymbolKey& that) const { return fName != that.fName; }
        struct Hash {
            uint32_t operator()(const SymbolKey& key) const { return key.fHash; }
        };
    };

    static SymbolKey MakeSymbolKey(std::string_view name) {
        return SymbolKey{name, SkOpts::hash_fn(name.data(), name.size(), 0)};
    }

    const Symbol* lookup(SymbolTable* writableSymbolTable,
                         bool encounteredModuleBoundary,
                         const SymbolKey& key);

    const Symbol* buildOverloadSet(SymbolTable* writableSymbolTable,
                                   bool encounteredModuleBoundary,
                                   const SymbolKey& key,
                                   const Symbol* symbol,
                                   SkSpan<const FunctionDeclaration* const> overloadSet);

    bool isType(const SymbolKey& key) const;

    bool fBuiltin = false;
    bool fAtModuleBoundary = false;
    std::forward_list<std::string> fOwnedStrings;
    SkTHashMap<SymbolKey, const Symbol*, SymbolKey::Hash> fSymbols;
    const Context& fContext;

    friend class Dehydrator;
};

/**
 * While in scope, the passed-in symbol table is replaced with a child symbol table.
 */
class AutoSymbolTable {
public:
    AutoSymbolTable(std::shared_ptr<SymbolTable>* s)
        : fSymbolTable(s) {
        SkDEBUGCODE(fPrevious = fSymbolTable->get();)
        SymbolTable::Push(fSymbolTable);
    }

    ~AutoSymbolTable() {
        SymbolTable::Pop(fSymbolTable);
        SkASSERT(fPrevious == fSymbolTable->get());
    }

    std::shared_ptr<SymbolTable>* fSymbolTable;
    SkDEBUGCODE(SymbolTable* fPrevious;)
};

}  // namespace SkSL

#endif
