refactor: 重构 FunctionBuilder

- 优化了 FunctionBuilder 类的文档注释,详细描述了其功能和处理流程
- 改进了 build 方法的内部逻辑,提高了代码可读性和可维护性
- 修复了返回类型为空时的处理逻辑,增加了鲁棒性
- 优化了默认字面量后缀的设置逻辑,提高了代码的灵活性
This commit is contained in:
Luke 2025-08-30 11:27:25 +08:00
parent db720ea357
commit cff45a9d17

View File

@ -12,14 +12,15 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
/** /**
* IR 函数构建器 * IR 函数构建器
* <p> * <p>
* 负责将语法树中的 FunctionNode 节点转化为可执行的 IRFunction * 将语法树中的 {@link FunctionNode} 转换为可执行的 {@link IRFunction}包含
* 包含参数声明返回类型推断函数体语句转换等步骤
*
* <ul> * <ul>
* <li>支持自动导入全局/跨模块常量使跨模块常量引用 ModuleA.a IR 阶段可用</li> * <li>在全局函数表登记函数名与返回类型</li>
* <li>将函数形参声明为虚拟寄存器并注册到作用域便于后续指令生成</li> * <li>初始化 IR 容器与构建上下文作用域寄存器池等</li>
* <li>根据返回类型设置表达式默认字面量类型保证 IR 层类型一致性</li> * <li>导入全局/跨模块常量便于常量折叠与跨模块引用</li>
* <li>遍历并转换函数体语句为 IR 指令</li> * <li>依据返回类型为表达式设置数字字面量默认后缀</li>
* <li>分配形参寄存器并注册到作用域与 IR 函数</li>
* <li>将函数体语句逐条转为 IR 指令</li>
* <li>在构建完成后清理默认字面量后缀避免泄漏到其它函数</li>
* </ul> * </ul>
*/ */
public class FunctionBuilder { public class FunctionBuilder {
@ -44,57 +45,56 @@ public class FunctionBuilder {
* @return 构建得到的 IRFunction 对象 * @return 构建得到的 IRFunction 对象
*/ */
public IRFunction build(FunctionNode functionNode) { public IRFunction build(FunctionNode functionNode) {
// 1) 在全局函数表登记名称 + 返回类型返回类型可能为 null例如构造函数 init
// 1. 在全局函数表注册函数名与返回类型
// 方便其他阶段/模块调用类型检查
GlobalFunctionTable.register(functionNode.name(), functionNode.returnType()); GlobalFunctionTable.register(functionNode.name(), functionNode.returnType());
// 2. 初始化 IRFunction 实例与上下文对象 // 2) 初始化 IR 容器与上下文
// IRFunction: 表示该函数的中间代码容器
// IRContext: 负责作用域寄存器分配等编译上下文管理
IRFunction irFunction = new IRFunction(functionNode.name()); IRFunction irFunction = new IRFunction(functionNode.name());
IRContext irContext = new IRContext(irFunction); IRContext irContext = new IRContext(irFunction);
// 3. 自动导入所有全局/跨模块常量到当前作用域 // 3) 导入所有全局/跨模块常量到当前作用域便于常量折叠和跨模块引用
// 支持如 ModuleA.a 这样的常量访问/折叠参见 ExpressionBuilder
GlobalConstTable.all().forEach((k, v) -> GlobalConstTable.all().forEach((k, v) ->
irContext.getScope().importExternalConst(k, v)); irContext.getScope().importExternalConst(k, v));
// 4. 根据函数返回类型设置默认类型后缀 // 4) 根据函数返回类型设置数字字面量默认后缀
// 例如返回类型为 double , 字面量表达式自动用 d 后缀 // - 关键修复 returnType 进行空值/空白保护缺省视为 "void"
char _returnSuffix = switch (functionNode.returnType().toLowerCase()) { String rt = functionNode.returnType();
String rtLower = (rt == null || rt.trim().isEmpty()) ? "void" : rt.trim().toLowerCase();
// 根据返回类型决定默认字面量后缀
// 仅在浮点/整型长短类型上设置其它/void 情况不设置使用 '\0' 表示不设置
char defaultSuffix = switch (rtLower) {
case "double" -> 'd'; case "double" -> 'd';
case "float" -> 'f'; case "float" -> 'f';
case "long" -> 'l'; case "long" -> 'l';
case "short" -> 's'; case "short" -> 's';
case "byte" -> 'b'; case "byte" -> 'b';
default -> '\0'; // 其它类型不设默认后缀 default -> '\0';
}; };
ExpressionUtils.setDefaultSuffix(_returnSuffix); ExpressionUtils.setDefaultSuffix(defaultSuffix);
try { try {
// 5. 遍历函数参数列表 // 5) 处理形参
// - 为每个分配一个新的虚拟寄存器 // - 为每个参分配一个新的虚拟寄存器 IRContext 统一分配保证作用域一致
// - 注册参数名类型寄存器到当前作用域 // - (参数名, 类型, 寄存器) 声明到当前作用域
// - 添加参数寄存器到 IRFunction用于后续调用与指令生成 // - 将寄存器加入 IRFunction 的参数列表便于后续调用/生成
for (ParameterNode p : functionNode.parameters()) { for (ParameterNode p : functionNode.parameters()) {
IRVirtualRegister reg = irFunction.newRegister(); IRVirtualRegister reg = irContext.newRegister(); // 使用上下文统一分配
irContext.getScope().declare(p.name(), p.type(), reg); irContext.getScope().declare(p.name(), p.type(), reg);
irFunction.addParameter(reg); irFunction.addParameter(reg);
} }
// 6. 遍历函数体语句节点转换为 IR 指令 // 6) 构建函数体将每条语句节点转换为 IR 指令序列
// StatementBuilder 负责将每条语句递归转换为 IR
StatementBuilder stmtBuilder = new StatementBuilder(irContext); StatementBuilder stmtBuilder = new StatementBuilder(irContext);
for (StatementNode stmt : functionNode.body()) { for (StatementNode stmt : functionNode.body()) {
stmtBuilder.build(stmt); stmtBuilder.build(stmt);
} }
} finally { } finally {
// 7. 清理默认类型后缀防止影响后续其他函数的类型推断 // 7) 清理默认后缀防止影响后续函数的字面量推断
ExpressionUtils.clearDefaultSuffix(); ExpressionUtils.clearDefaultSuffix();
} }
// 8. 返回构建完成的 IRFunction // 8) 返回构建完成的 IRFunction
return irFunction; return irFunction;
} }
} }