refactor: 重构表达式构建逻辑

- 优化常量折叠逻辑,使用 switch-case 结构替代 if-else
- 增加对链式方法调用的支持
- 调整函数调用构建流程,按被调用对象类型分支处理
- 优化参数传递逻辑,区分隐式 this 参数和显式参数- 规范化方法和函数名处理,自动补充模块名前缀
This commit is contained in:
Luke 2025-08-31 17:01:10 +08:00
parent 419057c3c2
commit 416f3fdeb1

View File

@ -411,46 +411,58 @@ public record ExpressionBuilder(IRContext ctx) {
* @return 编译期常量值支持 intdoubleStringList否则返回 null
*/
private Object tryFoldConst(ExpressionNode expr) {
if (expr == null) return null;
// 数字字面量尝试解析为 int double
if (expr instanceof NumberLiteralNode n) {
String s = n.value();
try {
if (s.contains(".") || s.contains("e") || s.contains("E"))
return Double.parseDouble(s); // 带小数或科学计数法为 double
return Integer.parseInt(s); // 否则为 int
} catch (NumberFormatException e) {
return null; // 无法解析为数字
switch (expr) {
case null -> {
return null;
}
}
// 字符串字面量直接返回字符串
if (expr instanceof StringLiteralNode s) return s.value();
// 布尔字面量true 返回 1false 返回 0
if (expr instanceof BoolLiteralNode b) return b.getValue() ? 1 : 0;
// 数组字面量递归折叠所有元素
if (expr instanceof ArrayLiteralNode arr) {
List<Object> list = new ArrayList<>();
for (ExpressionNode e : arr.elements()) {
Object v = tryFoldConst(e);
if (v == null) return null; // 有一项无法折叠则整体失败
list.add(v);
// 数字字面量尝试解析为 int double
case NumberLiteralNode n -> {
String s = n.value();
try {
if (s.contains(".") || s.contains("e") || s.contains("E"))
return Double.parseDouble(s); // 带小数或科学计数法为 double
return Integer.parseInt(s); // 否则为 int
} catch (NumberFormatException e) {
return null; // 无法解析为数字
}
}
return List.copyOf(list);
}
// 标识符尝试查找作用域中的常量值
if (expr instanceof IdentifierNode id) {
Object v = null;
try {
v = ctx.getScope().getConstValue(id.name());
} catch (Throwable ignored) {
// 查不到常量或异常都视为无法折叠
// 字符串字面量直接返回字符串
case StringLiteralNode s -> {
return s.value();
}
// 布尔字面量true 返回 1false 返回 0
case BoolLiteralNode b -> {
return b.getValue() ? 1 : 0;
}
// 数组字面量递归折叠所有元素
case ArrayLiteralNode arr -> {
List<Object> list = new ArrayList<>();
for (ExpressionNode e : arr.elements()) {
Object v = tryFoldConst(e);
if (v == null) return null; // 有一项无法折叠则整体失败
list.add(v);
}
return List.copyOf(list);
}
// 标识符尝试查找作用域中的常量值
case IdentifierNode id -> {
Object v = null;
try {
v = ctx.getScope().getConstValue(id.name());
} catch (Throwable ignored) {
// 查不到常量或异常都视为无法折叠
}
return v;
}
default -> {
}
return v;
}
// 其它类型不支持折叠返回 null
@ -535,12 +547,13 @@ public record ExpressionBuilder(IRContext ctx) {
/**
* 构建函数或方法调用表达式的 IR 指令并返回存放调用结果寄存器
* 构建函数或方法调用表达式的 IR 指令并返回结果寄存器
* <p>
* 支持以下两大类调用
* 支持类调用
* <ul>
* <li>普通函数调用 foo(a, b)</li>
* <li>成员方法调用 obj.method(a, b) ModuleName.func(a, b)</li>
* <li>普通函数调用foo(a, b)</li>
* <li>成员方法调用obj.method(a, b) ModuleName.func(a, b)</li>
* <li>链式方法调用obj.getAddr().getCity()</li>
* </ul>
* 核心流程
* <ol>
@ -555,52 +568,62 @@ public record ExpressionBuilder(IRContext ctx) {
* @throws IllegalStateException 被调用表达式类型不支持或参数异常
*/
private IRVirtualRegister buildCall(CallExpressionNode call) {
// 1. 先递归生成所有参数表达式对应的虚拟寄存器
// 1. 先递归生成显式参数的寄存器列表
List<IRVirtualRegister> explicitRegs = new ArrayList<>();
for (ExpressionNode a : call.arguments()) explicitRegs.add(build(a));
String callee; // 被调用方法/函数规范化后的名称
List<IRValue> finalArgs = new ArrayList<>(); // 最终传递给 Call 指令的参数表
String callee; // 函数/方法的规范化名字
List<IRValue> finalArgs = new ArrayList<>(); // 最终传递给 CALL 的参数表
// 2. 判断被调用对象callee类型
if (call.callee() instanceof MemberExpressionNode m && m.object() instanceof IdentifierNode idObj) {
// ==== 成员方法/模块函数调用 ====
// 分为两种情况
// a) 结构体实例方法 a.method(...)
// b) 模块静态函数 ModuleName.func(...)
// 2. callee 类型分支
switch (call.callee()) {
case MemberExpressionNode m when m.object() instanceof IdentifierNode idObj -> {
// ========= 情况 1: obj.method(...) ModuleName.func(...) =========
String recvName = idObj.name();
String recvType = ctx.getScope().lookupType(recvName);
String recvName = idObj.name(); // 接收者名字
String recvType = ctx.getScope().lookupType(recvName); // 查找接收者类型
if (recvType == null || recvType.isEmpty()) {
// 模块函数调用 "模块名.函数名"
callee = recvName + "." + m.member();
finalArgs.addAll(explicitRegs);
} else {
// 结构体实例方法调用 "类型名.方法名"且第一个参数为 this
callee = recvType + "." + m.member();
IRVirtualRegister thisReg = ctx.getScope().lookup(recvName);
if (thisReg == null)
throw new IllegalStateException("未定义标识符: " + recvName);
finalArgs.add(thisReg); // 隐式 this
finalArgs.addAll(explicitRegs); // 其它参数
}
}
case MemberExpressionNode m -> {
// ========= 情况 2: 通用成员调用 (支持链式调用) =========
// 例如 p.getAddr().getCity()
IRVirtualRegister objReg = build(m.object()); // 递归计算 object 表达式
if (recvType == null || recvType.isEmpty()) {
// 情况 b接收者不是变量而是模块名ModuleName.func
// 规范化函数名为 "模块名.成员名"参数直接用 explicitRegs
callee = recvName + "." + m.member();
callee = m.member(); // 直接用成员名
finalArgs.add(objReg); // 隐式 this
finalArgs.addAll(explicitRegs); // 其它参数
}
case IdentifierNode id -> {
// ========= 情况 3: 普通函数调用 foo(...) =========
String current = ctx.getFunction().name(); // 当前函数全名
int dot = current.lastIndexOf('.');
if (dot >= 0 && !id.name().contains(".")) {
// 自动补充模块名前缀
callee = current.substring(0, dot) + "." + id.name();
} else {
callee = id.name();
}
finalArgs.addAll(explicitRegs);
} else {
// 情况 a结构体实例方法obj.method(...)
// 方法名规范化为 "类型名.成员名"并将实例自身作为第一个参数
callee = recvType + "." + m.member();
IRVirtualRegister thisReg = ctx.getScope().lookup(recvName);
if (thisReg == null)
throw new IllegalStateException("未定义标识符: " + recvName);
finalArgs.add(thisReg); // 隐式 this 作为第一个参数
finalArgs.addAll(explicitRegs); // 其余参数
}
} else if (call.callee() instanceof IdentifierNode id) {
// ==== 普通函数调用 ====
// 继承当前命名空间前缀若当前函数为 ModuleName.xxx foo() 自动补前缀为 ModuleName.foo
String current = ctx.getFunction().name(); // 当前函数全名
int dot = current.lastIndexOf('.');
if (dot >= 0 && !id.name().contains(".")) {
callee = current.substring(0, dot) + "." + id.name();
} else {
callee = id.name();
}
finalArgs.addAll(explicitRegs);
} else {
// ==== 其它类型不支持 ====
throw new IllegalStateException("不支持的被调用表达式: " + call.callee().getClass().getSimpleName());
default ->
// ========= 其它不支持 =========
throw new IllegalStateException(
"不支持的被调用表达式: " + call.callee().getClass().getSimpleName());
}
// 3. 分配目标寄存器生成函数/方法调用指令
@ -609,7 +632,6 @@ public record ExpressionBuilder(IRContext ctx) {
return dest;
}
/**
* 二元表达式构建结果存储到新寄存器
* <br>