feat: 基本类型全类型比较支持
This commit is contained in:
parent
9d21eeace9
commit
a69cbb868a
@ -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());
|
||||
|
||||
@ -13,7 +13,7 @@ import java.util.Map;
|
||||
* <ul>
|
||||
* <li>维护在当前作用域中已声明变量的寄存器分配信息;</li>
|
||||
* <li>支持将已有虚拟寄存器与变量名重新绑定;</li>
|
||||
* <li>根据变量名查找对应的虚拟寄存器实例。</li>
|
||||
* <li>根据变量名查找对应的虚拟寄存器实例或类型。</li>
|
||||
* </ul>
|
||||
*/
|
||||
final class IRBuilderScope {
|
||||
@ -104,4 +104,12 @@ final class IRBuilderScope {
|
||||
String lookupType(String name) {
|
||||
return varTypes.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 变量->类型的映射 的不可变副本
|
||||
* @return 变量->类型的映射 的不可变副本
|
||||
*/
|
||||
Map<String, String> getVarTypes() {
|
||||
return Map.copyOf(varTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>类型宽度优先级</b>:D > F > L > I > S > B
|
||||
* <ul>
|
||||
* <li>D(double):6</li>
|
||||
* <li>F(float):5</li>
|
||||
* <li>L(long):4</li>
|
||||
* <li>I(int):3</li>
|
||||
* <li>S(short):2</li>
|
||||
* <li>B(byte):1</li>
|
||||
* <li>未识别类型:0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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<String, IROpCode> table = useLong ? IROpCodeMappings.CMP_L64
|
||||
: IROpCodeMappings.CMP_I32;
|
||||
public static IROpCode cmpOp(Map<String, String> variables, String op, ExpressionNode left, ExpressionNode right) {
|
||||
char typeLeft = analysisType(variables, left);
|
||||
char typeRight = analysisType(variables, right);
|
||||
char type = promote(typeLeft, typeRight);
|
||||
|
||||
Map<String, IROpCode> 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<String, String> 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'
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<String, String> variables, String op, ExpressionNode left, ExpressionNode right) {
|
||||
return ComparisonUtils.cmpOp(variables, op, left, right);
|
||||
}
|
||||
|
||||
/* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user