diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
index cf7816a..0bb5f16 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
@@ -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.x,a 的类型)
@@ -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}。
*
@@ -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 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));
- // 组装参数:arr、idx、value,调用 runtime 的 __setindex_r 填充元素
- List 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. 若确认为结构体,显式调用 .__init__N 完成字段初始化 */
+ if (IRBuilderScope.getStructLayout(newExpr.typeName()) != null) {
+ String ctor = newExpr.typeName() + ".__init__" + argRegs.size();
+ List 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) {
* 遍历所有构造参数,依次写入目标列表的 [0..n-1] 位置
* 最终返回该寄存器
*
+ *
* @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 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 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. 若为结构体实例,调用构造器 .__init__N */
+ if (IRBuilderScope.getStructLayout(node.typeName()) != null) {
+ String ctorName = node.typeName() + ".__init__" + argRegs.size();
+ List ctorArgs = new ArrayList<>();
+ ctorArgs.add(dest); // 隐式 this
+ ctorArgs.addAll(argRegs); // 构造实参
+ ctx.addInstruction(new CallInstruction(null, ctorName, ctorArgs));
}
- // 4. 返回最终保存新建对象/数组的寄存器
return dest;
}