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