refactor(irgen): 规范采用visitor生成

This commit is contained in:
jing
2026-03-18 02:07:34 +08:00
parent 7d4d60c546
commit dfa71bc0d7
8 changed files with 297 additions and 130 deletions

View File

@@ -17,58 +17,91 @@ std::string GetLValueName(SysYParser::LValueContext& lvalue) {
} // namespace
void IRGenImpl::GenBlock(SysYParser::BlockStmtContext& block) {
for (auto* item : block.blockItem()) {
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
for (auto* item : ctx->blockItem()) {
if (item) {
if (GenBlockItem(*item)) {
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
break;
}
}
}
return {};
}
bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) {
if (item.decl()) {
GenDecl(*item.decl());
return false;
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
SysYParser::BlockItemContext& item) {
return std::any_cast<BlockFlow>(item.accept(this));
}
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
}
if (item.stmt()) {
return GenStmt(*item.stmt());
if (ctx->decl()) {
ctx->decl()->accept(this);
return BlockFlow::Continue;
}
if (ctx->stmt()) {
return ctx->stmt()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
}
void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
if (!decl.btype() || !decl.btype()->INT()) {
// 变量声明的 IR 生成目前也是最小实现:
// - 先检查声明的基础类型,当前仅支持局部 int
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
//
// 和更完整的版本相比,这里还没有:
// - 一个 Decl 中多个变量定义的顺序处理;
// - const、数组、全局变量等不同声明形态
// - 更丰富的类型系统。
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
}
auto* var_def = decl.varDef();
auto* var_def = ctx->varDef();
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
}
GenVarDef(*var_def);
var_def->accept(this);
return {};
}
void IRGenImpl::GenVarDef(SysYParser::VarDefContext& decl) {
if (!decl.lValue()) {
// 当前仍是教学用的最小版本,因此这里只支持:
// - 局部 int 变量;
// - 标量初始化;
// - 一个 VarDef 对应一个槽位。
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
}
if (!ctx->lValue()) {
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
}
GetLValueName(*decl.lValue());
if (storage_map_.find(&decl) != storage_map_.end()) {
GetLValueName(*ctx->lValue());
if (storage_map_.find(ctx) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
}
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[&decl] = slot;
storage_map_[ctx] = slot;
ir::Value* init = nullptr;
if (auto* init_value = decl.initValue()) {
if (auto* init_value = ctx->initValue()) {
if (!init_value->exp()) {
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
}
init = GenExpr(*init_value->exp());
init = EvalExpr(*init_value->exp());
} else {
init = builder_.CreateConstInt(0);
}
builder_.CreateStore(init, slot);
return {};
}