// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/transform/remove_phonies.h"

#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/variable.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/scoped_assignment.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::RemovePhonies);

namespace tint::transform {
namespace {

struct SinkSignature {
    std::vector<const sem::Type*> types;

    bool operator==(const SinkSignature& other) const {
        if (types.size() != other.types.size()) {
            return false;
        }
        for (size_t i = 0; i < types.size(); i++) {
            if (types[i] != other.types[i]) {
                return false;
            }
        }
        return true;
    }

    struct Hasher {
        /// @param sig the CallTargetSignature to hash
        /// @return the hash value
        std::size_t operator()(const SinkSignature& sig) const {
            size_t hash = tint::utils::Hash(sig.types.size());
            for (auto* ty : sig.types) {
                tint::utils::HashCombine(&hash, ty);
            }
            return hash;
        }
    };
};

}  // namespace

RemovePhonies::RemovePhonies() = default;

RemovePhonies::~RemovePhonies() = default;

bool RemovePhonies::ShouldRun(const Program* program, const DataMap&) const {
    for (auto* node : program->ASTNodes().Objects()) {
        if (node->Is<ast::PhonyExpression>()) {
            return true;
        }
    }
    return false;
}

void RemovePhonies::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
    auto& sem = ctx.src->Sem();

    std::unordered_map<SinkSignature, Symbol, SinkSignature::Hasher> sinks;

    for (auto* node : ctx.src->ASTNodes().Objects()) {
        if (auto* stmt = node->As<ast::AssignmentStatement>()) {
            if (stmt->lhs->Is<ast::PhonyExpression>()) {
                std::vector<const ast::Expression*> side_effects;
                if (!ast::TraverseExpressions(
                        stmt->rhs, ctx.dst->Diagnostics(), [&](const ast::CallExpression* expr) {
                            // ast::CallExpression may map to a function or builtin call
                            // (both may have side-effects), or a type constructor or
                            // type conversion (both do not have side effects).
                            auto* call = sem.Get<sem::Call>(expr);
                            if (!call) {
                                // Semantic node must be a Materialize, in which case the expression
                                // was creation-time (compile time), so could not have side effects.
                                // Just skip.
                                return ast::TraverseAction::Skip;
                            }
                            if (call->Target()->IsAnyOf<sem::Function, sem::Builtin>()) {
                                side_effects.push_back(expr);
                                return ast::TraverseAction::Skip;
                            }
                            return ast::TraverseAction::Descend;
                        })) {
                    return;
                }

                if (side_effects.empty()) {
                    // Phony assignment with no side effects.
                    // Just remove it.
                    RemoveStatement(ctx, stmt);
                    continue;
                }

                if (side_effects.size() == 1) {
                    if (auto* call = side_effects[0]->As<ast::CallExpression>()) {
                        // Phony assignment with single call side effect.
                        // Replace phony assignment with call.
                        ctx.Replace(stmt, [&, call] { return ctx.dst->CallStmt(ctx.Clone(call)); });
                        continue;
                    }
                }

                // Phony assignment with multiple side effects.
                // Generate a call to a placeholder function with the side
                // effects as arguments.
                ctx.Replace(stmt, [&, side_effects] {
                    SinkSignature sig;
                    for (auto* arg : side_effects) {
                        sig.types.push_back(sem.Get(arg)->Type()->UnwrapRef());
                    }
                    auto sink = utils::GetOrCreate(sinks, sig, [&] {
                        auto name = ctx.dst->Symbols().New("phony_sink");
                        ast::ParameterList params;
                        for (auto* ty : sig.types) {
                            auto* ast_ty = CreateASTTypeFor(ctx, ty);
                            params.push_back(
                                ctx.dst->Param("p" + std::to_string(params.size()), ast_ty));
                        }
                        ctx.dst->Func(name, params, ctx.dst->ty.void_(), {});
                        return name;
                    });
                    ast::ExpressionList args;
                    for (auto* arg : side_effects) {
                        args.push_back(ctx.Clone(arg));
                    }
                    return ctx.dst->CallStmt(ctx.dst->Call(sink, args));
                });
            }
        }
    }

    ctx.Clone();
}

}  // namespace tint::transform
