#include "irgen/IRGen.h"

#include <stdexcept>

#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"

void IRGenImpl::GenBlock(SysYParser::BlockContext& block) {
  for (auto* item : block.blockItem()) {
    if (item) {
      if (GenBlockItem(*item)) {
        // 当前语法要求 return 为块内最后一条语句；命中后可停止生成。
        break;
      }
    }
  }
}

bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) {
  if (item.decl()) {
    GenDecl(*item.decl());
    return false;
  }
  if (item.stmt()) {
    return GenStmt(*item.stmt());
  }
  throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
}

void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
  if (decl.varDecl()) {
    GenVarDecl(*decl.varDecl());
    return;
  }
  throw std::runtime_error(FormatError("irgen", "暂不支持的声明类型"));
}

void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
  if (storage_map_.find(&decl) != storage_map_.end()) {
    throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
  }
  auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
  storage_map_[&decl] = slot;

  ir::Value* init = nullptr;
  if (decl.exp()) {
    init = GenExpr(*decl.exp());
  } else {
    init = builder_.CreateConstInt(0);
  }
  builder_.CreateStore(init, slot);
}
