/*
 * 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/private/SkSLString.h"
#include "include/private/SkSLSymbol.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"
#include "include/sksl/SkSLErrorReporter.h"

#include <forward_list>
#include <memory>
#include <vector>

namespace SkSL {

class Context;
class FunctionDeclaration;

/**
 * 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);

    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;
    }

    template <typename T>
    const T* takeOwnershipOfIRNode(std::unique_ptr<T> node) {
        const T* ptr = node.get();
        fOwnedNodes.push_back(std::move(node));
        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;
    }

    /**
     * Returns the built-in symbol table that this SymbolTable rests upon.
     * If this symbol table is already a built-in, it will be returned as-is.
     */
    SkSL::SymbolTable* builtinParent() {
        return this->isBuiltin() ? this : fParent->builtinParent();
    }

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

    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, const SymbolKey& key);

    static std::vector<const FunctionDeclaration*> GetFunctions(const Symbol& s);

    bool fBuiltin = false;
    std::vector<std::unique_ptr<IRNode>> fOwnedNodes;
    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
