// SSA 值体系抽象：
// - 常量、参数、指令结果等统一为 Value
// - 提供类型信息与使用/被使用关系（按需要实现）
#include "ir/IR.h"

#include <algorithm>

namespace ir {

Value::Value(std::shared_ptr<Type> ty, std::string name)
    : type_(std::move(ty)), name_(std::move(name)) {}

const std::shared_ptr<Type>& Value::GetType() const { return type_; }

const std::string& Value::GetName() const { return name_; }

void Value::SetName(std::string n) { name_ = std::move(n); }

bool Value::IsVoid() const { return type_ && type_->IsVoid(); }

bool Value::IsInt32() const { return type_ && type_->IsInt32(); }

bool Value::IsPtrInt32() const { return type_ && type_->IsPtrInt32(); }

bool Value::IsConstant() const {
  return dynamic_cast<const ConstantValue*>(this) != nullptr;
}

bool Value::IsInstruction() const {
  return dynamic_cast<const Instruction*>(this) != nullptr;
}

bool Value::IsUser() const {
  return dynamic_cast<const User*>(this) != nullptr;
}

bool Value::IsFunction() const {
  return dynamic_cast<const Function*>(this) != nullptr;
}

void Value::AddUse(User* user, size_t operand_index) {
  if (!user) return;
  uses_.push_back(Use(this, user, operand_index));
}

void Value::RemoveUse(User* user, size_t operand_index) {
  uses_.erase(
      std::remove_if(uses_.begin(), uses_.end(),
                     [&](const Use& use) {
                       return use.GetUser() == user &&
                              use.GetOperandIndex() == operand_index;
                     }),
      uses_.end());
}

const std::vector<Use>& Value::GetUses() const { return uses_; }

void Value::ReplaceAllUsesWith(Value* new_value) {
  if (!new_value) {
    throw std::runtime_error("ReplaceAllUsesWith 缺少 new_value");
  }
  if (new_value == this) {
    return;
  }

  auto uses = uses_;
  for (const auto& use : uses) {
    auto* user = use.GetUser();
    if (!user) continue;
    size_t operand_index = use.GetOperandIndex();
    if (user->GetOperand(operand_index) == this) {
      user->SetOperand(operand_index, new_value);
    }
  }
}

ConstantValue::ConstantValue(std::shared_ptr<Type> ty, std::string name)
    : Value(std::move(ty), std::move(name)) {}

ConstantInt::ConstantInt(std::shared_ptr<Type> ty, int v)
    : ConstantValue(std::move(ty), ""), value_(v) {}

}  // namespace ir
