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

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

#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"

TINT_INSTANTIATE_TYPEINFO(tint::transform::Unshadow);

namespace tint {
namespace transform {

/// The PIMPL state for the Unshadow transform
struct Unshadow::State {
  /// The clone context
  CloneContext& ctx;

  /// Constructor
  /// @param context the clone context
  explicit State(CloneContext& context) : ctx(context) {}

  /// Performs the transformation
  void Run() {
    auto& sem = ctx.src->Sem();

    // Maps a variable to its new name.
    std::unordered_map<const sem::Variable*, Symbol> renamed_to;

    auto rename = [&](const sem::Variable* var) -> const ast::Variable* {
      auto* decl = var->Declaration();
      auto name = ctx.src->Symbols().NameFor(decl->symbol);
      auto symbol = ctx.dst->Symbols().New(name);
      renamed_to.emplace(var, symbol);

      auto source = ctx.Clone(decl->source);
      auto* type = ctx.Clone(decl->type);
      auto* constructor = ctx.Clone(decl->constructor);
      auto decorations = ctx.Clone(decl->decorations);
      return ctx.dst->create<ast::Variable>(
          source, symbol, decl->declared_storage_class, decl->declared_access,
          type, decl->is_const, constructor, decorations);
    };

    ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {
      if (auto* local = sem.Get<sem::LocalVariable>(var)) {
        if (local->Shadows()) {
          return rename(local);
        }
      }
      if (auto* param = sem.Get<sem::Parameter>(var)) {
        if (param->Shadows()) {
          return rename(param);
        }
      }
      return nullptr;
    });
    ctx.ReplaceAll([&](const ast::IdentifierExpression* ident)
                       -> const tint::ast::IdentifierExpression* {
      if (auto* user = sem.Get<sem::VariableUser>(ident)) {
        auto it = renamed_to.find(user->Variable());
        if (it != renamed_to.end()) {
          return ctx.dst->Expr(it->second);
        }
      }
      return nullptr;
    });
    ctx.Clone();
  }
};

Unshadow::Unshadow() = default;

Unshadow::~Unshadow() = default;

void Unshadow::Run(CloneContext& ctx, const DataMap&, DataMap&) {
  State(ctx).Run();
}

}  // namespace transform
}  // namespace tint
