/*
 * Copyright (c) 2023 Apple Inc. All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
 */

#include "config.h"
#include "MangleNames.h"

#include "AST.h"
#include "ASTScopedVisitorInlines.h"
#include "CallGraph.h"
#include "ContextProviderInlines.h"
#include "WGSL.h"
#include "WGSLShaderModule.h"
#include <wtf/HashSet.h>
#include <wtf/text/MakeString.h>

namespace WGSL {

struct MangledName {
    enum Kind : uint8_t {
        Type,
        Local,
        Global,
        Parameter,
        Function,
        Field,
    };
    static constexpr unsigned numberOfKinds = 6;

    Kind kind;
    uint32_t index;
    String originalName;

    String toString() const
    {
        static const auto prefixes = std::to_array<ASCIILiteral>({
            "type"_s,
            "local"_s,
            "global"_s,
            "parameter"_s,
            "function"_s,
            "field"_s,
        });
        return makeString(prefixes[WTF::enumToUnderlyingType(kind)], String::number(index));
    }
};

class NameManglerVisitor : public AST::ScopedVisitor<MangledName> {
    using Base = AST::ScopedVisitor<MangledName>;
    using Base::visit;

public:
    NameManglerVisitor(ShaderModule& shaderModule)
        : m_shaderModule(shaderModule)
    {
    }

    void run();

    void visit(AST::Function&) override;
    void visit(AST::Parameter&) override;
    void visit(AST::VariableStatement&) override;
    void visit(AST::Structure&) override;
    void visit(AST::Variable&) override;
    void visit(AST::IdentifierExpression&) override;
    void visit(AST::FieldAccessExpression&) override;

private:
    using NameMap = ContextProvider::ContextMap;

    void introduceVariable(AST::Identifier&, MangledName::Kind);
    void readVariable(AST::Identifier&) const;

    MangledName makeMangledName(const String&, MangledName::Kind);

    void visitVariableDeclaration(AST::Variable&, MangledName::Kind);

    ShaderModule& m_shaderModule;
    HashMap<AST::Structure*, NameMap> m_structFieldMapping;
    std::array<uint32_t, MangledName::numberOfKinds> m_indexPerType { 0 };
};

void NameManglerVisitor::run()
{
    Base::visit(m_shaderModule);
}

void NameManglerVisitor::visit(AST::Function& function)
{
    String originalName = function.name();
    introduceVariable(function.name(), MangledName::Function);
    Base::visit(function);
}

void NameManglerVisitor::visit(AST::Parameter& parameter)
{
    Base::visit(parameter.typeName());
    introduceVariable(parameter.name(), MangledName::Parameter);
}

void NameManglerVisitor::visit(AST::Structure& structure)
{
    introduceVariable(structure.name(), MangledName::Type);

    NameMap fieldMap;
    for (auto& member : structure.members()) {
        Base::visit(member.type());
        auto mangledName = makeMangledName(member.name(), MangledName::Field);
        fieldMap.add(member.name(), mangledName);
        m_shaderModule.replace(&member.name(), AST::Identifier::makeWithSpan(member.name().span(), mangledName.toString()));
    }
    auto result = m_structFieldMapping.add(&structure, WTFMove(fieldMap));
    ASSERT_UNUSED(result, result.isNewEntry);
}

void NameManglerVisitor::visit(AST::Variable& variable)
{
    visitVariableDeclaration(variable, MangledName::Global);
}

void NameManglerVisitor::visit(AST::VariableStatement& variable)
{
    visitVariableDeclaration(variable.variable(), MangledName::Local);
}

void NameManglerVisitor::visitVariableDeclaration(AST::Variable& variable, MangledName::Kind kind)
{
    Base::visit(variable);

    introduceVariable(variable.name(), kind);
}

void NameManglerVisitor::visit(AST::IdentifierExpression& identifier)
{
    readVariable(identifier.identifier());
}

void NameManglerVisitor::visit(AST::FieldAccessExpression& access)
{
    Base::visit(access);

    auto* baseType = access.base().inferredType();
    if (auto* reference = std::get_if<Types::Reference>(baseType))
        baseType = reference->element;
    if (auto* pointer = std::get_if<Types::Pointer>(baseType))
        baseType = pointer->element;
    auto* structType = std::get_if<Types::Struct>(baseType);
    if (!structType)
        return;
    auto structMapIt = m_structFieldMapping.find(&structType->structure);
    RELEASE_ASSERT(structMapIt != m_structFieldMapping.end());

    auto fieldIt = structMapIt->value.find(access.fieldName());
    ASSERT(fieldIt != structMapIt->value.end());
    m_shaderModule.replace(&access.fieldName(), AST::Identifier::makeWithSpan(access.fieldName().span(), fieldIt->value.toString()));
}

void NameManglerVisitor::introduceVariable(AST::Identifier& name, MangledName::Kind kind)
{
    const auto* mangledName = ContextProvider::introduceVariable(name, makeMangledName(name, kind));
    ASSERT(mangledName);
    m_shaderModule.replace(&name, AST::Identifier::makeWithSpan(name.span(), mangledName->toString()));
}

MangledName NameManglerVisitor::makeMangledName(const String& name, MangledName::Kind kind)
{
    return MangledName {
        kind,
        m_indexPerType[WTF::enumToUnderlyingType(kind)]++,
        name
    };
}

void NameManglerVisitor::readVariable(AST::Identifier& name) const
{
    if (const auto* mangledName = ContextProvider::readVariable(name))
        m_shaderModule.replace(&name, AST::Identifier::makeWithSpan(name.span(), mangledName->toString()));
}

void mangleNames(ShaderModule& shaderModule)
{
    NameManglerVisitor(shaderModule).run();
}

} // namespace WGSL
