feat: 支持结构体字段赋值

- 增加对 this.<field> 结构体字段赋值的支持
- 优化赋值语句处理逻辑,优先考虑局部/参数变量- 修复字段写入后的常量绑定问题
- 优化变量声明和初始化流程
This commit is contained in:
Luke 2025-08-30 11:28:42 +08:00
parent cff45a9d17
commit 513aeba2bc

View File

@ -84,8 +84,58 @@ public class StatementBuilder {
expr.build(exp);
return;
}
// ===== 赋值语句 =====
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, NodeContext _)) {
// 1) 优先当作已存在的局部/参数变量赋值保持原有行为
final String type = ctx.getScope().lookupType(var);
IRVirtualRegister localReg = ctx.getScope().lookup(var);
if (localReg != null) {
ctx.setVarType(type);
expr.buildInto(rhs, localReg);
// 赋值时尝试记录/清除常量
try {
Object constVal = tryFoldConst(rhs);
if (constVal != null) ctx.getScope().setConstValue(var, constVal);
else ctx.getScope().clearConstValue(var);
} catch (Throwable ignored) {}
ctx.clearVarType();
return;
}
// 2) 若不是局部变量尝试将裸标识符视为 this.<field> 的结构体字段赋值
IRVirtualRegister thisReg = ctx.getScope().lookup("this");
String thisType = ctx.getScope().lookupType("this");
if (thisReg != null && thisType != null) {
java.util.Map<String, Integer> layout = ctx.getScope().getStructLayout(thisType);
if (layout == null) {
// 兼容 "Module.Struct" 与简单名 "Struct"
int dot = thisType.lastIndexOf('.');
if (dot >= 0 && dot + 1 < thisType.length()) {
layout = ctx.getScope().getStructLayout(thisType.substring(dot + 1));
}
}
Integer idx = (layout != null) ? layout.get(var) : null;
if (idx != null) {
// 生成右值
IRVirtualRegister valReg = expr.build(rhs);
// 字段槽位下标常量
IRVirtualRegister idxReg = InstructionFactory.loadConst(ctx, idx);
// __setindex_r 写入字段与构造写入/读取对齐
java.util.List<org.jcnc.snow.compiler.ir.core.IRValue> argv =
java.util.List.of(thisReg, idxReg, valReg);
ctx.addInstruction(new org.jcnc.snow.compiler.ir.instruction.CallInstruction(
null, "__setindex_r", argv));
// 字段写入后清理该标识符的常量绑定避免误当作本地常量
try { ctx.getScope().clearConstValue(var); } catch (Throwable ignored) {}
return;
}
}
// 3) 否则退回为声明/绑定一个新的局部变量并赋值与原逻辑一致
ctx.setVarType(type);
IRVirtualRegister target = getOrDeclareRegister(var, type);
expr.buildInto(rhs, target);
@ -97,8 +147,7 @@ public class StatementBuilder {
ctx.getScope().setConstValue(var, constVal);
else
ctx.getScope().clearConstValue(var);
} catch (Throwable ignored) {
}
} catch (Throwable ignored) {}
ctx.clearVarType();
return;
@ -163,11 +212,9 @@ public class StatementBuilder {
ctx.setVarType(decl.getType());
// 2. 为当前声明的变量分配一个全新的虚拟寄存器
// 这样可以保证该变量和初始值表达式中的变量物理上独立不会发生别名/串扰
IRVirtualRegister dest = ctx.newRegister();
// 3. 将初始值表达式的计算结果写入新分配的寄存器
// 即使初始值是某个已存在变量 outer_i这里是值的拷贝
expr.buildInto(decl.getInitializer().get(), dest);
// 声明赋初值时登记常量
@ -177,8 +224,7 @@ public class StatementBuilder {
ctx.getScope().setConstValue(decl.getName(), constVal);
else
ctx.getScope().clearConstValue(decl.getName());
} catch (Throwable ignored) {
}
} catch (Throwable ignored) {}
ctx.clearVarType();
ctx.getScope().declare(decl.getName(), decl.getType(), dest);
@ -188,18 +234,18 @@ public class StatementBuilder {
}
return;
}
if (stmt instanceof ReturnNode ret) {
// return 语句
if (ret.getExpression().isPresent()) {
// return 带返回值
IRVirtualRegister r = expr.build(ret.getExpression().get());
InstructionFactory.ret(ctx, r);
} else {
// return 无返回值
InstructionFactory.retVoid(ctx);
}
return;
}
if (stmt instanceof BreakNode) {
// break 语句跳转到当前最近一层循环的结束标签
if (breakTargets.isEmpty()) {
@ -208,6 +254,7 @@ public class StatementBuilder {
InstructionFactory.jmp(ctx, breakTargets.peek());
return;
}
if (stmt instanceof ContinueNode) {
// continue 语句跳转到当前最近一层循环的 step 起始标签
if (continueTargets.isEmpty()) {
@ -216,10 +263,12 @@ public class StatementBuilder {
InstructionFactory.jmp(ctx, continueTargets.peek());
return;
}
// 不支持的语句类型
throw new IllegalStateException("Unsupported statement: " + stmt.getClass().getSimpleName() + ": " + stmt);
}
/**
* 获取变量名对应的寄存器如果尚未声明则新声明一个并返回
*