// 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;
    }

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

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::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;
    }
    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, ctx->dst->Diagnostics())
              << "Unknown global declaration type";
        });
  }
}

}  // namespace ast
}  // namespace tint
