// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_LANG_CORE_IR_MODULE_H_
#define SRC_TINT_LANG_CORE_IR_MODULE_H_

#include <memory>
#include <string>

#include "src/tint/lang/core/constant/manager.h"
#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/constant.h"
#include "src/tint/lang/core/ir/function.h"
#include "src/tint/lang/core/ir/instruction.h"
#include "src/tint/lang/core/ir/value.h"
#include "src/tint/lang/core/type/manager.h"
#include "src/tint/utils/containers/const_propagating_ptr.h"
#include "src/tint/utils/containers/filtered_iterator.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/diagnostic/source.h"
#include "src/tint/utils/id/generation_id.h"
#include "src/tint/utils/memory/block_allocator.h"
#include "src/tint/utils/result/result.h"
#include "src/tint/utils/symbol/symbol_table.h"

namespace tint::core::ir {

/// Main module class for the IR.
class Module {
    /// Program Id required to create other components
    GenerationID prog_id_;

    /// Map of value to name
    Hashmap<const Value*, Symbol, 32> value_to_name_;

    /// A predicate function that returns true if the instruction or value is alive.
    struct IsAlive {
        bool operator()(const Instruction* instruction) const { return instruction->Alive(); }
        bool operator()(const Value* value) const { return value->Alive(); }
    };

  public:
    /// Constructor
    Module();
    /// Move constructor
    /// @param o the module to move from
    Module(Module&& o);
    /// Destructor
    ~Module();

    /// Move assign
    /// @param o the module to assign from
    /// @returns a reference to this module
    Module& operator=(Module&& o);

    /// @param inst the instruction
    /// @return the name of the given instruction, or an invalid symbol if the instruction is not
    /// named or does not have a single return value.
    Symbol NameOf(const Instruction* inst) const;

    /// @param value the value
    /// @return the name of the given value, or an invalid symbol if the value is not named.
    Symbol NameOf(const Value* value) const;

    /// @param inst the instruction to set the name of
    /// @param name the desired name of the value. May be suffixed on collision.
    /// @note requires the instruction be a single result instruction.
    void SetName(Instruction* inst, std::string_view name);

    /// @param value the value to name.
    /// @param name the desired name of the value. May be suffixed on collision.
    void SetName(Value* value, std::string_view name);

    /// @param value the value to name
    /// @param name the desired name of the value
    void SetName(Value* value, Symbol name);

    /// Removes the name from @p value
    /// @param value the value to remove the name from
    void ClearName(Value* value);

    /// @return the type manager for the module
    core::type::Manager& Types() { return constant_values.types; }

    /// @return the type manager for the module
    const core::type::Manager& Types() const { return constant_values.types; }

    /// @returns a iterable of all the alive instructions
    FilteredIterable<IsAlive, BlockAllocator<Instruction>::View> Instructions() {
        return {allocators.instructions.Objects()};
    }

    /// @returns a iterable of all the alive instructions
    FilteredIterable<IsAlive, BlockAllocator<Instruction>::ConstView> Instructions() const {
        return {allocators.instructions.Objects()};
    }

    /// @returns a iterable of all the alive values
    FilteredIterable<IsAlive, BlockAllocator<Value>::View> Values() {
        return {allocators.values.Objects()};
    }

    /// @returns a iterable of all the alive values
    FilteredIterable<IsAlive, BlockAllocator<Value>::ConstView> Values() const {
        return {allocators.values.Objects()};
    }

    /// The block allocator
    BlockAllocator<Block> blocks;

    /// The constant value manager
    core::constant::Manager constant_values;

    /// The various BlockAllocators for the module
    struct {
        /// The instruction allocator
        BlockAllocator<Instruction> instructions;

        /// The value allocator
        BlockAllocator<Value> values;
    } allocators;

    /// List of functions in the program
    Vector<ConstPropagatingPtr<Function>, 8> functions;

    /// The block containing module level declarations, if any exist.
    ConstPropagatingPtr<Block> root_block;

    /// The symbol table for the module
    SymbolTable symbols{prog_id_};

    /// The map of core::constant::Value to their ir::Constant.
    Hashmap<const core::constant::Value*, ir::Constant*, 16> constants;
};

}  // namespace tint::core::ir

#endif  // SRC_TINT_LANG_CORE_IR_MODULE_H_
