// IR Function：
// - 保存参数列表、基本块列表
// - 记录函数属性/元信息（按需要扩展）
#include "ir/IR.h"

#include <stdexcept>

#include "utils/Log.h"

namespace ir {

Argument::Argument(std::shared_ptr<Type> ty, std::string name, size_t index)
    : Value(std::move(ty), std::move(name)), arg_index_(index) {}

Function::Function(std::string name, std::shared_ptr<Type> ret_type,
                   std::vector<std::shared_ptr<Type>> param_types)
    : Value(std::move(ret_type), std::move(name)),
      param_types_(std::move(param_types)) {
  for (size_t i = 0; i < param_types_.size(); ++i) {
    args_.push_back(std::make_unique<Argument>(
        param_types_[i], "%arg" + std::to_string(i), i));
  }
  entry_ = CreateBlock("entry");
}

BasicBlock* Function::CreateBlock(const std::string& name) {
  auto block = std::make_unique<BasicBlock>(name);
  auto* ptr = block.get();
  ptr->SetParent(this);
  blocks_.push_back(std::move(block));
  if (!entry_) {
    entry_ = ptr;
  }
  return ptr;
}

BasicBlock* Function::GetEntry() { return entry_; }

const BasicBlock* Function::GetEntry() const { return entry_; }

const std::vector<std::shared_ptr<Type>>& Function::GetParamTypes() const {
  return param_types_;
}

size_t Function::GetNumParams() const { return param_types_.size(); }

Argument* Function::GetArgument(size_t index) const {
  if (index >= args_.size()) {
    throw std::out_of_range(FormatError("ir", "Argument 索引越界"));
  }
  return args_[index].get();
}

const std::vector<std::unique_ptr<BasicBlock>>& Function::GetBlocks() const {
  return blocks_;
}

}  // namespace ir
