feat: 支持结构体初始化构造器调用

- 在 new 表达式中添加结构体初始化逻辑
- 生成空列表后,依次填充构造参数
- 若为结构体类型,显式调用 __init__构造器方法
- 优化了字段访问和数组初始化的代码结构
This commit is contained in:
Luke 2025-09-01 16:39:52 +08:00
parent 6428ba5cbd
commit 5f6751b3d4

View File

@ -128,10 +128,10 @@ public record ExpressionBuilder(IRContext ctx) {
// ===== 2. 结构体/对象字段访问 =====
// (1) 递归构建成员对象 a.b先获得 a 的寄存器
// 1 递归构建成员对象 a.b先获得 a 的寄存器
IRVirtualRegister objReg = build(mem.object());
// (2) 尝试解析成员访问接收者object的类型
// 2 尝试解析成员访问接收者object的类型
String ownerType = null;
if (mem.object() instanceof IdentifierNode oid) {
// 如果对象是标识符直接查询其类型例如 a.xa 的类型
@ -147,14 +147,14 @@ public record ExpressionBuilder(IRContext ctx) {
throw new IllegalStateException("无法解析成员访问接收者的类型");
}
// (3) 查找字段槽位下标ownerType mem.member() 字段的序号
// 3 查找字段槽位下标ownerType mem.member() 字段的序号
Integer fieldIndex = ctx.getScope().lookupFieldIndex(ownerType, mem.member());
if (fieldIndex == null) {
// 字段不存在抛出异常
throw new IllegalStateException("类型 " + ownerType + " 不存在字段: " + mem.member());
}
// (4) 生成读取字段的 IR 指令CALL __index_r, objReg, const(fieldIndex)
// 4 生成读取字段的 IR 指令CALL __index_r, objReg, const(fieldIndex)
// 4.1 先将字段下标加载到寄存器
IRVirtualRegister idxReg = ctx.newRegister();
ctx.addInstruction(new LoadConstInstruction(
@ -172,7 +172,6 @@ public record ExpressionBuilder(IRContext ctx) {
}
/**
* 将表达式节点 {@link ExpressionNode} 的求值结果写入指定的目标虚拟寄存器 {@code dest}
* <p>
@ -208,24 +207,35 @@ public record ExpressionBuilder(IRContext ctx) {
// ===================== new 表达式构造数组/对象 =====================
// 生成空数组然后按参数依次初始化每一项使用 __setindex_r 填充目标寄存器
case NewExpressionNode newExpr -> {
// 步骤1先写入空 List目标寄存器 dest
// 1. 把空列表写入目标寄存器
InstructionFactory.loadConstInto(ctx, dest, new IRConstant(java.util.List.of()));
// 步骤2依次写入构造参数填充各下标项
// 2. 依次写入构造实参同时缓存参数寄存器
List<IRVirtualRegister> argRegs = new ArrayList<>();
for (int i = 0; i < newExpr.arguments().size(); i++) {
IRVirtualRegister argReg = build(newExpr.arguments().get(i)); // 参数值寄存器
IRVirtualRegister idxReg = ctx.newTempRegister(); // 下标寄存器
IRVirtualRegister argReg = build(newExpr.arguments().get(i));
argRegs.add(argReg);
IRVirtualRegister idxReg = ctx.newTempRegister();
InstructionFactory.loadConstInto(ctx, idxReg, new IRConstant(i));
// 组装参数arridxvalue调用 runtime __setindex_r 填充元素
List<IRValue> args = new ArrayList<>();
args.add(dest); // 数组本身
args.add(idxReg); // 下标
args.add(argReg); // 元素值
ctx.addInstruction(new CallInstruction(null, "__setindex_r", args));
ctx.addInstruction(new CallInstruction(
null,
"__setindex_r",
List.of(dest, idxReg, argReg)));
}
/* 3. 若确认为结构体,显式调用 <Struct>.__init__N 完成字段初始化 */
if (IRBuilderScope.getStructLayout(newExpr.typeName()) != null) {
String ctor = newExpr.typeName() + ".__init__" + argRegs.size();
List<IRValue> ctorArgs = new ArrayList<>();
ctorArgs.add(dest); // this
ctorArgs.addAll(argRegs); // 实参
ctx.addInstruction(new CallInstruction(null, ctor, ctorArgs));
}
}
// ===================== 变量标识符 =====================
// x查找符号表move 到目标寄存器未定义时报错
case IdentifierNode id -> {
@ -514,6 +524,7 @@ public record ExpressionBuilder(IRContext ctx) {
* <li>遍历所有构造参数依次写入目标列表的 [0..n-1] 位置</li>
* <li>最终返回该寄存器</li>
* </ul>
*
* @param node new 表达式节点包含所有构造参数
* @return 保存新创建对象/数组引用的目标寄存器
*/
@ -521,27 +532,32 @@ public record ExpressionBuilder(IRContext ctx) {
// 1. 分配新的寄存器作为 new 表达式的结果
IRVirtualRegister dest = ctx.newRegister();
// 2. 先写入一个空列表常量由后端 R_PUSH runtime 扩展为动态对象/列表
/* 1. 写入空列表 */
InstructionFactory.loadConstInto(ctx, dest, new IRConstant(java.util.List.of()));
// 3. 遍历所有构造参数依次写入目标列表的 [0..n-1] 下标位置
/* 2. 创建参数并写入列表,同时缓存参数寄存器 */
List<IRVirtualRegister> argRegs = new ArrayList<>();
for (int i = 0; i < node.arguments().size(); i++) {
// 3.1 构造第 i 个参数的值存入 argReg
IRVirtualRegister argReg = build(node.arguments().get(i));
// 3.2 临时分配一个寄存器 idxReg 存储下标 i
argRegs.add(argReg);
IRVirtualRegister idxReg = ctx.newTempRegister();
InstructionFactory.loadConstInto(ctx, idxReg, new IRConstant(i));
// 3.3 调用 runtime __setindex_r 写入元素
List<IRValue> args = new ArrayList<>();
args.add(dest); // 目标列表对象
args.add(idxReg); // 当前下标
args.add(argReg); // 参数值
ctx.addInstruction(new CallInstruction(null, "__setindex_r", args));
ctx.addInstruction(new CallInstruction(
null, "__setindex_r",
List.of(dest, idxReg, argReg)));
}
/* 3. 若为结构体实例,调用构造器 <Struct>.__init__N */
if (IRBuilderScope.getStructLayout(node.typeName()) != null) {
String ctorName = node.typeName() + ".__init__" + argRegs.size();
List<IRValue> ctorArgs = new ArrayList<>();
ctorArgs.add(dest); // 隐式 this
ctorArgs.addAll(argRegs); // 构造实参
ctx.addInstruction(new CallInstruction(null, ctorName, ctorArgs));
}
// 4. 返回最终保存新建对象/数组的寄存器
return dest;
}