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

#include <utility>

#include "src/ast/type_decl.h"
#include "src/program_builder.h"

TINT_INSTANTIATE_TYPEINFO(tint::ast::Module);

namespace tint {
namespace ast {

Module::Module(ProgramID pid, const Source& src) : Base(pid, src) {}

Module::Module(ProgramID pid,
               const Source& src,
               std::vector<const ast::Node*> global_decls)
    : Base(pid, src), global_declarations_(std::move(global_decls)) {
  for (auto* decl : global_declarations_) {
    if (decl == nullptr) {
      continue;
    }
    diag::List diags;
    BinGlobalDeclaration(decl, diags);
  }
}

Module::~Module() = default;

const ast::TypeDecl* Module::LookupType(Symbol name) const {
  for (auto* ty : TypeDecls()) {
    if (ty->name == name) {
      return ty;
    }
  }
  return nullptr;
}

void Module::AddGlobalDeclaration(const tint::ast::Node* decl) {
  diag::List diags;
  BinGlobalDeclaration(decl, diags);
  global_declarations_.emplace_back(decl);
}

void Module::BinGlobalDeclaration(const tint::ast::Node* decl,
                                  diag::List& diags) {
  Switch(
      decl,  //
      [&](const ast::TypeDecl* type) {
        TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
        type_decls_.push_back(type);
      },
      [&](const Function* func) {
        TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
        functions_.push_back(func);
      },
      [&](const Variable* var) {
        TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
        global_variables_.push_back(var);
      },
      [&](Default) {
        TINT_ICE(AST, diags) << "Unknown global declaration type";
      });
}

void Module::AddGlobalVariable(const ast::Variable* var) {
  TINT_ASSERT(AST, var);
  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
  global_variables_.push_back(var);
  global_declarations_.push_back(var);
}

void Module::AddTypeDecl(const ast::TypeDecl* type) {
  TINT_ASSERT(AST, type);
  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
  type_decls_.push_back(type);
  global_declarations_.push_back(type);
}

void Module::AddFunction(const ast::Function* func) {
  TINT_ASSERT(AST, func);
  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
  functions_.push_back(func);
  global_declarations_.push_back(func);
}

const Module* Module::Clone(CloneContext* ctx) const {
  auto* out = ctx->dst->create<Module>();
  out->Copy(ctx, this);
  return out;
}

void Module::Copy(CloneContext* ctx, const Module* src) {
  ctx->Clone(global_declarations_, src->global_declarations_);

  // During the clone, declarations may have been placed into the module.
  // Clear everything out, as we're about to re-bin the declarations.
  type_decls_.clear();
  functions_.clear();
  global_variables_.clear();

  for (auto* decl : global_declarations_) {
    if (!decl) {
      TINT_ICE(AST, ctx->dst->Diagnostics())
          << "src global declaration was nullptr";
      continue;
    }
    BinGlobalDeclaration(decl, ctx->dst->Diagnostics());
  }
}

}  // namespace ast
}  // namespace tint
