From a69cbb868a37846640a900f17a2c875a89ea1cfe Mon Sep 17 00:00:00 2001
From: zhangxun <1958638841@qq.com>
Date: Thu, 10 Jul 2025 19:14:37 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9F=BA=E6=9C=AC=E7=B1=BB=E5=9E=8B?=
=?UTF-8?q?=E5=85=A8=E7=B1=BB=E5=9E=8B=E6=AF=94=E8=BE=83=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ir/builder/ExpressionBuilder.java | 4 +-
.../compiler/ir/builder/IRBuilderScope.java | 10 +-
.../compiler/ir/builder/StatementBuilder.java | 2 +-
.../compiler/ir/utils/ComparisonUtils.java | 103 ++++++++++++++++--
.../compiler/ir/utils/ExpressionUtils.java | 4 +-
5 files changed, 107 insertions(+), 16 deletions(-)
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 f53d8cc..bb8c32e 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
@@ -145,7 +145,7 @@ public record ExpressionBuilder(IRContext ctx) {
if (ComparisonUtils.isComparisonOperator(op)) {
return InstructionFactory.binOp(
ctx,
- ComparisonUtils.cmpOp(op, bin.left(), bin.right()),
+ ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()),
left, right);
}
@@ -171,7 +171,7 @@ public record ExpressionBuilder(IRContext ctx) {
if (ComparisonUtils.isComparisonOperator(op)) {
InstructionFactory.binOpInto(
ctx,
- ComparisonUtils.cmpOp(op, bin.left(), bin.right()),
+ ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()),
a, b, dest);
} else {
IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right());
diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java
index e0fd4cf..3cd5deb 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java
@@ -13,7 +13,7 @@ import java.util.Map;
*
* - 维护在当前作用域中已声明变量的寄存器分配信息;
* - 支持将已有虚拟寄存器与变量名重新绑定;
- * - 根据变量名查找对应的虚拟寄存器实例。
+ * - 根据变量名查找对应的虚拟寄存器实例或类型。
*
*/
final class IRBuilderScope {
@@ -104,4 +104,12 @@ final class IRBuilderScope {
String lookupType(String name) {
return varTypes.get(name);
}
+
+ /**
+ * 获取 变量->类型的映射 的不可变副本
+ * @return 变量->类型的映射 的不可变副本
+ */
+ Map getVarTypes() {
+ return Map.copyOf(varTypes);
+ }
}
diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java
index 78e42fa..30d672a 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java
@@ -218,7 +218,7 @@ public class StatementBuilder {
IRVirtualRegister b = expr.build(right);
// 使用适配后位宽正确的比较指令
- IROpCode cmp = ComparisonUtils.cmpOp(operator, left, right);
+ IROpCode cmp = ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), operator, left, right);
IROpCode falseOp = IROpCodeUtils.invert(cmp);
InstructionFactory.cmpJump(ctx, falseOp, a, b, falseLabel);
diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java
index 70ac8f5..3cc8e37 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java
@@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.ir.utils;
import org.jcnc.snow.compiler.ir.core.IROpCode;
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
+import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
@@ -25,26 +26,108 @@ public final class ComparisonUtils {
return IROpCodeMappings.CMP_I32.containsKey(op);
}
+ /**
+ * 类型宽度优先级:D > F > L > I > S > B
+ *
+ * - D(double):6
+ * - F(float):5
+ * - L(long):4
+ * - I(int):3
+ * - S(short):2
+ * - B(byte):1
+ * - 未识别类型:0
+ *
+ *
+ * @param p 类型标记字符
+ * @return 优先级数值(越大类型越宽)
+ */
+ private static int rank(char p) {
+ return switch (p) {
+ case 'D' -> 6;
+ case 'F' -> 5;
+ case 'L' -> 4;
+ case 'I' -> 3;
+ case 'S' -> 2;
+ case 'B' -> 1;
+ default -> 0;
+ };
+ }
+
+ /**
+ * 返回更“宽”的公共类型(即优先级高的类型)。
+ *
+ * @param a 类型标记字符 1
+ * @param b 类型标记字符 2
+ * @return 宽度更高的类型标记字符
+ */
+ public static char promote(char a, char b) {
+ return rank(a) >= rank(b) ? a : b;
+ }
+
/**
* 返回符合操作数位宽的比较 IROpCode。
*
- * @param op 比较符号(==, !=, <, >, <=, >=)
- * @param left 左操作数 AST
- * @param right 右操作数 AST
+ * @param variables 变量->类型的映射
+ * @param op 比较符号(==, !=, <, >, <=, >=)
+ * @param left 左操作数 AST
+ * @param right 右操作数 AST
*/
- public static IROpCode cmpOp(String op, ExpressionNode left, ExpressionNode right) {
- boolean useLong = isLongLiteral(left) || isLongLiteral(right);
- Map table = useLong ? IROpCodeMappings.CMP_L64
- : IROpCodeMappings.CMP_I32;
+ public static IROpCode cmpOp(Map variables, String op, ExpressionNode left, ExpressionNode right) {
+ char typeLeft = analysisType(variables, left);
+ char typeRight = analysisType(variables, right);
+ char type = promote(typeLeft, typeRight);
+
+ Map table = switch (type) {
+ case 'B' -> IROpCodeMappings.CMP_B8;
+ case 'S' -> IROpCodeMappings.CMP_S16;
+ case 'I' -> IROpCodeMappings.CMP_I32;
+ case 'L' -> IROpCodeMappings.CMP_L64;
+ case 'F' -> IROpCodeMappings.CMP_F32;
+ case 'D' -> IROpCodeMappings.CMP_D64;
+ default -> throw new IllegalStateException("Unexpected value: " + type);
+ };
+
return table.get(op);
}
/* ------------ 内部工具 ------------ */
- private static boolean isLongLiteral(ExpressionNode node) {
+ private static char analysisType(Map variables, ExpressionNode node) {
if (node instanceof NumberLiteralNode(String value, NodeContext _)) {
- return value.endsWith("L") || value.endsWith("l");
+ char suffix = Character.toUpperCase(value.charAt(value.length() - 1));
+ if ("BSILFD".indexOf(suffix) != -1) {
+ return suffix;
+ }
+ if (value.indexOf('.') != -1) {
+ return 'D';
+ }
+
+ return 'I'; // 默认为 'I'
}
- return false; // 变量暂不处理(后续可扩展符号表查询)
+ if (node instanceof IdentifierNode(String name, NodeContext _)) {
+ final String type = variables.get(name);
+ switch (type) {
+ case "byte" -> {
+ return 'B';
+ }
+ case "short" -> {
+ return 'S';
+ }
+ case "int" -> {
+ return 'I';
+ }
+ case "long" -> {
+ return 'L';
+ }
+ case "float" -> {
+ return 'F';
+ }
+ case "double" -> {
+ return 'D';
+ }
+ }
+ }
+
+ return 'I'; // 默认为 'I'
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java
index 2eed575..ba6f663 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java
@@ -120,8 +120,8 @@ public final class ExpressionUtils {
/**
* 推荐调用:根据左右表达式类型自动选择 int / long 比较指令。
*/
- public static IROpCode cmpOp(String op, ExpressionNode left, ExpressionNode right) {
- return ComparisonUtils.cmpOp(op, left, right);
+ public static IROpCode cmpOp(Map variables, String op, ExpressionNode left, ExpressionNode right) {
+ return ComparisonUtils.cmpOp(variables, op, left, right);
}
/* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */