feat: 更新 FunctionBuilder构建流程与文档

- 在全局函数表中注册函数名与返回类型
- 初始化 IRFunction 实例与 IRContext 上下文对象
- 自动导入全局常量(包括跨模块 const 变量)到当前作用域
- 根据函数返回类型设置表达式推断的默认字面量类型后缀
- 遍历声明形参,每个参数分配虚拟寄存器,并注册到作用域
- 依次转换函数体中的每条语句为 IR指令
- 函数体转换完成后,清理默认类型后缀
This commit is contained in:
Luke 2025-08-26 11:32:48 +08:00
parent fcdc3a49f8
commit 1a0c3a38cb

View File

@ -1,5 +1,6 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.common.GlobalConstTable;
import org.jcnc.snow.compiler.ir.common.GlobalFunctionTable;
import org.jcnc.snow.compiler.ir.core.IRFunction;
import org.jcnc.snow.compiler.ir.utils.ExpressionUtils;
@ -13,6 +14,13 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
* <p>
* 负责将语法树中的 FunctionNode 节点转化为可执行的 IRFunction
* 包含参数声明返回类型推断函数体语句转换等步骤
*
* <ul>
* <li>支持自动导入全局/跨模块常量使跨模块常量引用 ModuleA.a IR 阶段可用</li>
* <li>将函数形参声明为虚拟寄存器并注册到作用域便于后续指令生成</li>
* <li>根据返回类型设置表达式默认字面量类型保证 IR 层类型一致性</li>
* <li>遍历并转换函数体语句为 IR 指令</li>
* </ul>
*/
public class FunctionBuilder {
@ -21,11 +29,15 @@ public class FunctionBuilder {
* <p>
* 构建过程包括:
* <ol>
* <li>初始化 IRFunction 实例和上下文</li>
* <li>根据函数返回类型设置默认类型后缀便于表达式推断</li>
* <li>声明参数到作用域并为每个参数分配虚拟寄存器</li>
* <li>遍历并转换函数体内的每条语句为 IR 指令</li>
* <li>函数构建完成后清理默认类型后缀防止影响其他函数</li>
* <li>在全局函数表注册函数签名便于后续模块/语义分析阶段查询</li>
* <li>初始化 IRFunction 实例和 IRContext 上下文对象包含作用域与寄存器信息</li>
* <li>自动导入全局常量包括跨模块 const 变量到当前作用域
* 使成员访问如 ModuleA.a 可直接折叠为常量</li>
* <li>根据函数返回类型设置表达式推断的默认字面量类型后缀
* doubled, floatf避免类型不一致</li>
* <li>遍历声明形参每个参数分配虚拟寄存器并注册到作用域</li>
* <li>依次转换函数体中的每条语句为 IR 指令</li>
* <li>函数体转换完成后清理默认类型后缀防止影响后续函数构建</li>
* </ol>
*
* @param functionNode 表示函数定义的语法树节点
@ -33,44 +45,56 @@ public class FunctionBuilder {
*/
public IRFunction build(FunctionNode functionNode) {
// 在全局函数表中注册函数信息
// 1. 在全局函数表注册函数名与返回类型
// 方便其他阶段/模块调用类型检查
GlobalFunctionTable.register(functionNode.name(), functionNode.returnType());
// 0) 基本初始化: 创建 IRFunction 实例与对应上下文
// 2. 初始化 IRFunction 实例与上下文对象
// IRFunction: 表示该函数的中间代码容器
// IRContext: 负责作用域寄存器分配等编译上下文管理
IRFunction irFunction = new IRFunction(functionNode.name());
IRContext irContext = new IRContext(irFunction);
// 1) 把函数返回类型注入为默认类型后缀供表达式类型推断
// 3. 自动导入所有全局/跨模块常量到当前作用域
// 支持如 ModuleA.a 这样的常量访问/折叠参见 ExpressionBuilder
GlobalConstTable.all().forEach((k, v) ->
irContext.getScope().importExternalConst(k, v));
// 4. 根据函数返回类型设置默认类型后缀
// 例如返回类型为 double , 字面量表达式自动用 d 后缀
char _returnSuffix = switch (functionNode.returnType().toLowerCase()) {
case "double" -> 'd';
case "float" -> 'f';
case "long" -> 'l';
case "short" -> 's';
case "byte" -> 'b';
default -> '\0';
default -> '\0'; // 其它类型不设默认后缀
};
ExpressionUtils.setDefaultSuffix(_returnSuffix);
try {
// 2) 声明形参: 为每个参数分配虚拟寄存器并声明到作用域
// 5. 遍历函数参数列表
// - 为每个参数分配一个新的虚拟寄存器
// - 注册参数名类型寄存器到当前作用域
// - 添加参数寄存器到 IRFunction用于后续调用与指令生成
for (ParameterNode p : functionNode.parameters()) {
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
irContext.getScope().declare(p.name(), p.type(), reg); // 变量名寄存器绑定
irFunction.addParameter(reg); // 添加到函数参数列表
IRVirtualRegister reg = irFunction.newRegister();
irContext.getScope().declare(p.name(), p.type(), reg);
irFunction.addParameter(reg);
}
// 3) 生成函数体 IR: 遍历每条语句逐一转化
// 6. 遍历函数体语句节点转换为 IR 指令
// StatementBuilder 负责将每条语句递归转换为 IR
StatementBuilder stmtBuilder = new StatementBuilder(irContext);
for (StatementNode stmt : functionNode.body()) {
stmtBuilder.build(stmt);
}
} finally {
// 4) 清除默认后缀避免影响后续函数的推断
// 7. 清理默认类型后缀防止影响后续其他函数的类型推断
ExpressionUtils.clearDefaultSuffix();
}
// 返回构建好 IRFunction
// 8. 返回构建完成 IRFunction
return irFunction;
}
}