#include "irgen/IRGen.h"

#include <stdexcept>

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

ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) {
  if (!expr.addExp()) {
    throw std::runtime_error("[irgen] 非法表达式");
  }
  return GenAddExpr(*expr.addExp());
}

ir::Value* IRGenImpl::GenAddExpr(SysYParser::AddExpContext& add) {
  const auto& terms = add.primary();
  if (terms.empty()) {
    throw std::runtime_error("[irgen] 空加法表达式");
  }

  ir::Value* acc = GenPrimary(*terms[0]);
  for (size_t i = 1; i < terms.size(); ++i) {
    ir::Value* rhs = GenPrimary(*terms[i]);
    std::string name = ir::DefaultContext().NextTemp();
    acc = builder_.CreateBinary(ir::Opcode::Add, acc, rhs, name);
  }
  return acc;
}

ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
  if (primary.Number()) {
    return ir::DefaultContext().GetConstInt(std::stoi(primary.Number()->getText()));
  }
  if (primary.Ident()) {
    const std::string name = primary.Ident()->getText();
    auto it = locals_.find(name);
    if (it == locals_.end()) {
      throw std::runtime_error("[irgen] 变量未找到: " + name);
    }
    return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp());
  }
  if (primary.exp()) {
    return GenExpr(*primary.exp());
  }
  throw std::runtime_error("[irgen] 暂不支持的 primary 形式");
}
