// 当前仅支持 void、i32 和 i32*。
#include "ir/IR.h"

namespace ir {

Type::Type(Kind k) : kind_(k) {}

const std::shared_ptr<Type>& Type::GetVoidType() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Void);
  return type;
}

const std::shared_ptr<Type>& Type::GetInt32Type() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int32);
  return type;
}

const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::PtrInt32);
  return type;
}

const std::shared_ptr<Type>& Type::GetFloatType() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Float);
  return type;
}

const std::shared_ptr<Type>& Type::GetPtrFloatType() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::PtrFloat);
  return type;
}

const std::shared_ptr<Type>& Type::GetLabelType() {
  static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Label);
  return type;
}

Type::Kind Type::GetKind() const { return kind_; }

bool Type::IsVoid() const { return kind_ == Kind::Void; }

bool Type::IsInt32() const { return kind_ == Kind::Int32; }

bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }

bool Type::IsFloat() const { return kind_ == Kind::Float; }

bool Type::IsPtrFloat() const { return kind_ == Kind::PtrFloat; }

bool Type::IsLabel() const { return kind_ == Kind::Label; }

bool Type::IsArray() const { return kind_ == Kind::Array; }

std::shared_ptr<class ArrayType> Type::GetAsArrayType() {
  if (IsArray()) {
    return std::static_pointer_cast<ArrayType>(shared_from_this());
  }
  return nullptr;
}

ArrayType::ArrayType(std::shared_ptr<Type> element_type, uint32_t num_elements)
    : Type(Kind::Array),
      element_type_(std::move(element_type)),
      num_elements_(num_elements) {}

std::shared_ptr<ArrayType> ArrayType::Get(std::shared_ptr<Type> element_type,
                                          uint32_t num_elements) {
  return std::make_shared<ArrayType>(std::move(element_type), num_elements);
}

}  // namespace ir
