// 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/transform/remove_phonies.h"

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

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

TINT_INSTANTIATE_TYPEINFO(tint::transform::RemovePhonies);

namespace tint {
namespace 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* call) {
                  // ast::CallExpression may map to a function or intrinsic call
                  // (both may have side-effects), or a type constructor or
                  // type conversion (both do not have side effects).
                  if (sem.Get(call)
                          ->Target()
                          ->IsAnyOf<sem::Function, sem::Intrinsic>()) {
                    side_effects.push_back(call);
                    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 dummy 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::VariableList 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 transform
}  // namespace tint
