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 1b5afaf..d85f6bd 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.ir.core.IROpCode; import org.jcnc.snow.compiler.ir.instruction.CallInstruction; import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction; import org.jcnc.snow.compiler.ir.instruction.UnaryOperationInstruction; +import org.jcnc.snow.compiler.ir.utils.ComparisonUtils; import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.ir.utils.ExpressionUtils; @@ -137,13 +138,18 @@ public record ExpressionBuilder(IRContext ctx) { */ private IRVirtualRegister buildBinary(BinaryExpressionNode bin) { String op = bin.operator(); - IRVirtualRegister left = build(bin.left()); + IRVirtualRegister left = build(bin.left()); IRVirtualRegister right = build(bin.right()); - // 处理比较操作符 - if (ExpressionUtils.isComparisonOperator(op)) { - return InstructionFactory.binOp(ctx, ExpressionUtils.cmpOp(op), left, right); + + // 1. 比较运算 + if (ComparisonUtils.isComparisonOperator(op)) { + return InstructionFactory.binOp( + ctx, + ComparisonUtils.cmpOp(op, bin.left(), bin.right()), + left, right); } - // 处理算术运算符 + + // 2. 其他算术 / 逻辑运算 IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right()); if (code == null) throw new IllegalStateException("不支持的运算符: " + op); return InstructionFactory.binOp(ctx, code, left, right); @@ -161,8 +167,12 @@ public record ExpressionBuilder(IRContext ctx) { IRVirtualRegister a = build(bin.left()); IRVirtualRegister b = build(bin.right()); String op = bin.operator(); - if (ExpressionUtils.isComparisonOperator(op)) { - InstructionFactory.binOpInto(ctx, ExpressionUtils.cmpOp(op), a, b, dest); + + if (ComparisonUtils.isComparisonOperator(op)) { + InstructionFactory.binOpInto( + ctx, + ComparisonUtils.cmpOp(op, bin.left(), bin.right()), + a, b, dest); } else { IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right()); if (code == null) throw new IllegalStateException("不支持的运算符: " + op); 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 7459107..230dbd5 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 @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.ir.builder; import org.jcnc.snow.compiler.ir.core.IROpCode; -import org.jcnc.snow.compiler.ir.utils.ExpressionUtils; +import org.jcnc.snow.compiler.ir.utils.ComparisonUtils; import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.*; @@ -18,23 +18,41 @@ import java.util.Locale; */ public class StatementBuilder { - /** 当前 IR 上下文,包含作用域、指令序列等信息。 */ + /** + * 当前 IR 上下文,包含作用域、指令序列等信息。 + */ private final IRContext ctx; - /** 表达式 IR 构建器,用于将表达式节点转为 IR 指令。 */ + /** + * 表达式 IR 构建器,用于将表达式节点转为 IR 指令。 + */ private final ExpressionBuilder expr; /** * 构造方法。 + * * @param ctx IR 编译上下文环境 */ public StatementBuilder(IRContext ctx) { - this.ctx = ctx; + this.ctx = ctx; this.expr = new ExpressionBuilder(ctx); } + private static char typeSuffixFromType(String type) { + if (type == null) return '\0'; + return switch (type.toLowerCase(Locale.ROOT)) { + case "byte" -> 'b'; + case "short" -> 's'; + case "long" -> 'l'; + case "float" -> 'f'; + case "double" -> 'd'; + default -> '\0'; // 其余默认按 32-bit 整型处理 + }; + } + /** * 将一个 AST 语句节点转为 IR 指令序列。 * 根据节点类型分发到对应的处理方法。 + * * @param stmt 待转换的语句节点 */ public void build(StatementNode stmt) { @@ -107,6 +125,7 @@ public class StatementBuilder { /** * 获取变量名对应的寄存器,不存在则声明一个新的。 + * * @param name 变量名 * @return 变量对应的虚拟寄存器 */ @@ -121,6 +140,7 @@ public class StatementBuilder { /** * 批量构建一组语句节点,顺序处理每个语句。 + * * @param stmts 语句节点集合 */ private void buildStatements(Iterable stmts) { @@ -130,12 +150,13 @@ public class StatementBuilder { /** * 构建循环语句(for/while)。 * 处理流程:初始语句 → 条件判断 → 循环体 → 更新语句 → 跳回条件。 + * * @param loop 循环节点 */ private void buildLoop(LoopNode loop) { if (loop.initializer() != null) build(loop.initializer()); String lblStart = ctx.newLabel(); - String lblEnd = ctx.newLabel(); + String lblEnd = ctx.newLabel(); // 循环开始标签 InstructionFactory.label(ctx, lblStart); @@ -155,11 +176,12 @@ public class StatementBuilder { /** * 构建分支语句(if/else)。 * 处理流程:条件判断 → then 分支 → else 分支(可选)。 + * * @param ifNode if 语句节点 */ private void buildIf(IfNode ifNode) { String lblElse = ctx.newLabel(); - String lblEnd = ctx.newLabel(); + String lblEnd = ctx.newLabel(); // 条件不成立则跳转到 else emitConditionalJump(ifNode.condition(), lblElse); @@ -178,35 +200,30 @@ public class StatementBuilder { /** * 条件跳转指令的生成。 * 如果是二元比较表达式,直接使用对应比较操作码;否则等价于与 0 比较。 - * @param cond 条件表达式 + * + * @param cond 条件表达式 * @param falseLabel 条件不成立时跳转到的标签 */ private void emitConditionalJump(ExpressionNode cond, String falseLabel) { - if (cond instanceof BinaryExpressionNode(ExpressionNode left, String operator, ExpressionNode right) - && ExpressionUtils.isComparisonOperator(operator)) { - // 如果是比较操作(如 ==, >, <),直接生成对应的条件跳转 + if (cond instanceof BinaryExpressionNode( + ExpressionNode left, + String operator, + ExpressionNode right + ) + && ComparisonUtils.isComparisonOperator(operator)) { + IRVirtualRegister a = expr.build(left); IRVirtualRegister b = expr.build(right); - // 获取反向比较操作码 - IROpCode falseOp = IROpCodeUtils.invert(ExpressionUtils.cmpOp(operator)); + + // 使用适配后位宽正确的比较指令 + IROpCode cmp = ComparisonUtils.cmpOp(operator, left, right); + IROpCode falseOp = IROpCodeUtils.invert(cmp); + InstructionFactory.cmpJump(ctx, falseOp, a, b, falseLabel); } else { - // 否则将 cond 与 0 比较,相等则跳转 IRVirtualRegister condReg = expr.build(cond); - IRVirtualRegister zero = InstructionFactory.loadConst(ctx, 0); + IRVirtualRegister zero = InstructionFactory.loadConst(ctx, 0); InstructionFactory.cmpJump(ctx, IROpCode.CMP_EQ, condReg, zero, falseLabel); } } - - private static char typeSuffixFromType(String type) { - if (type == null) return '\0'; - return switch (type.toLowerCase(Locale.ROOT)) { - case "byte" -> 'b'; - case "short" -> 's'; - case "long" -> 'l'; - case "float" -> 'f'; - case "double" -> 'd'; - default -> '\0'; // 其余默认按 32-bit 整型处理 - }; - } } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java index 78f38f0..6efd59b 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java @@ -9,12 +9,12 @@ public final class IROpCodeMappings { private IROpCodeMappings() {} // 禁止实例化 // 8位整型运算符映射 - public static final Map OP_I8 = Map.of( + public static final Map OP_B8 = Map.of( "+", IROpCode.ADD_B8, "-", IROpCode.SUB_B8, "*", IROpCode.MUL_B8, "/", IROpCode.DIV_B8 ); // 16位整型 - public static final Map OP_I16 = Map.of( + public static final Map OP_S16 = Map.of( "+", IROpCode.ADD_S16, "-", IROpCode.SUB_S16, "*", IROpCode.MUL_S16, "/", IROpCode.DIV_S16 ); @@ -38,8 +38,20 @@ public final class IROpCodeMappings { "+", IROpCode.ADD_D64, "-", IROpCode.SUB_D64, "*", IROpCode.MUL_D64, "/", IROpCode.DIV_D64 ); - // 比较操作符映射 - public static final Map CMP = Map.of( + + /* ────── 比较运算符映射 ────── */ + /** 32-bit(int)比较 */ + public static final Map CMP_I32 = Map.of( + "==", IROpCode.CMP_EQ, + "!=", IROpCode.CMP_NE, + "<", IROpCode.CMP_LT, + ">", IROpCode.CMP_GT, + "<=", IROpCode.CMP_LE, + ">=", IROpCode.CMP_GE + ); + + /** 64-bit(long)比较 */ + public static final Map CMP_L64 = Map.of( "==", IROpCode.CMP_LEQ, "!=", IROpCode.CMP_LNE, "<", IROpCode.CMP_LLT, @@ -47,4 +59,6 @@ public final class IROpCodeMappings { "<=", IROpCode.CMP_LLE, ">=", IROpCode.CMP_LGE ); + + } 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 new file mode 100644 index 0000000..a284c12 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java @@ -0,0 +1,47 @@ +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.NumberLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; + +import java.util.Map; + +/** + * 比较运算辅助工具: + * 根据左右操作数类型(目前通过字面量后缀 L/l 判定)选择 + * 正确的 IR 比较指令,保证 int/long 均能正常运行。 + */ +public final class ComparisonUtils { + private ComparisonUtils() {} + + /** 判断给定操作符是否为比较运算符 */ + public static boolean isComparisonOperator(String op) { + // 两张表 key 完全一致,只需检查一张 + return IROpCodeMappings.CMP_I32.containsKey(op); + } + + /** + * 返回符合操作数位宽的比较 IROpCode。 + * + * @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; + return table.get(op); + } + + /* ------------ 内部工具 ------------ */ + + private static boolean isLongLiteral(ExpressionNode node) { + if (node instanceof NumberLiteralNode n) { + String v = n.value(); + return v.endsWith("L") || v.endsWith("l"); + } + return false; // 变量暂不处理(后续可扩展符号表查询) + } +} 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 8d48011..7c93c9a 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 @@ -12,99 +12,83 @@ import java.util.Map; /** * 表达式分析与运算符辅助工具类。 - *

- * 主要功能包括: + * + *

主要功能:

*
    *
  • 字面量常量的解析与类型推断
  • - *
  • 自动匹配操作码
  • - *
  • 表达式类型合并与判定
  • + *
  • 自动匹配算术/比较操作码
  • + *
  • 表达式类型合并与提升
  • *
*/ -public class ExpressionUtils { +public final class ExpressionUtils { - /** 用于存储默认的类型后缀(如函数返回类型),线程隔离。 */ + private ExpressionUtils() {} + + /* ────────────────── 线程级默认类型后缀 ────────────────── */ + + /** 默认类型后缀(如当前函数返回类型),线程隔离。 */ private static final ThreadLocal DEFAULT_SUFFIX = ThreadLocal.withInitial(() -> '\0'); - /** - * 在进入函数 IR 构建前设置默认的类型后缀(比如函数返回类型)。 - * @param suffix 默认后缀字符,如 'i', 'l', 'f', 'd' 等 - */ - public static void setDefaultSuffix(char suffix) { - DEFAULT_SUFFIX.set(suffix); - } + public static void setDefaultSuffix(char suffix) { DEFAULT_SUFFIX.set(suffix); } - /** - * 在函数 IR 构建结束后清除默认后缀,避免影响后续分析。 - */ - public static void clearDefaultSuffix() { - DEFAULT_SUFFIX.set('\0'); - } + public static void clearDefaultSuffix() { DEFAULT_SUFFIX.set('\0'); } + + /* ───────────────────── 字面量 & 常量 ───────────────────── */ /** * 解析整数字面量字符串,自动去除类型后缀(b/s/l/f/d/B/S/L/F/D),并转换为 int。 - * - * @param literal 字面量字符串,如 "123", "123l", "42B" - * @return 解析得到的 int 整数 */ public static int parseIntSafely(String literal) { - // 去掉类型后缀,只保留数字部分 String digits = literal.replaceAll("[bslfdBSDLF]$", ""); return Integer.parseInt(digits); } /** - * 根据数字字面量字符串自动判断类型,生成对应类型的 IRConstant。 - * 支持 b/s/l/f/d 类型后缀与浮点格式,自动分配合适类型。 - * - * @param ctx IR 编译上下文环境 - * @param value 字面量字符串(如 "1", "2l", "3.14f", "5D") - * @return 生成的 IRConstant 对象,包含正确类型 + * 根据数字字面量字符串自动判断类型,生成对应类型的 {@link IRConstant}。 + * 支持 b/s/l/f/d 后缀与浮点格式。 */ public static IRConstant buildNumberConstant(IRContext ctx, String value) { - char suffix = value.isEmpty() ? '\0' : Character.toLowerCase(value.charAt(value.length() - 1)); + char suffix = value.isEmpty() ? '\0' + : Character.toLowerCase(value.charAt(value.length() - 1)); + String digits = switch (suffix) { case 'b','s','l','f','d' -> value.substring(0, value.length() - 1); default -> { + /* 如果字面量本身没有后缀,则回退到变量目标类型(如声明语句左值) */ if (ctx.getVarType() != null) { - final var receiverType = ctx.getVarType(); - switch (receiverType) { - case "byte" -> suffix = 'b'; - case "short" -> suffix = 's'; - case "int" -> suffix = 'i'; - case "long" -> suffix = 'l'; - case "float" -> suffix = 'f'; - case "double" -> suffix = 'd'; - } + String t = ctx.getVarType(); + suffix = switch (t) { + case "byte" -> 'b'; + case "short" -> 's'; + case "int" -> 'i'; + case "long" -> 'l'; + case "float" -> 'f'; + case "double" -> 'd'; + default -> '\0'; + }; } - yield value; } }; - // 根据类型后缀或数值格式创建常量 + + /* 创建常量 */ return switch (suffix) { case 'b' -> new IRConstant(Byte.parseByte(digits)); case 's' -> new IRConstant(Short.parseShort(digits)); case 'l' -> new IRConstant(Long.parseLong(digits)); case 'f' -> new IRConstant(Float.parseFloat(digits)); case 'd' -> new IRConstant(Double.parseDouble(digits)); - default -> looksLikeFloat(digits) + default -> looksLikeFloat(digits) ? new IRConstant(Double.parseDouble(digits)) : new IRConstant(Integer.parseInt(digits)); }; } + /* ────────────────────── 一元运算 ────────────────────── */ + /** - * 根据表达式节点推断一元取负(-)运算应使用的操作码。 - * - *

优先级与 {@link #resolveOpCode} 使用的类型提升规则保持一致:

- *
    - *
  • 字面量或标识符带显式后缀时,直接以后缀决定位宽;
  • - *
  • 未显式指定时,默认使用 32 位整型 {@link IROpCode#NEG_I32}。
  • - *
- * - * @param operand 一元取负运算的操作数 - * @return 匹配的 {@link IROpCode} + * 推断一元取负(-)运算应使用的 {@link IROpCode}。 */ public static IROpCode negOp(ExpressionNode operand) { char t = typeChar(operand); @@ -114,113 +98,82 @@ public class ExpressionUtils { case 'l' -> IROpCode.NEG_L64; case 'f' -> IROpCode.NEG_F32; case 'd' -> IROpCode.NEG_D64; - default -> IROpCode.NEG_I32; + default -> IROpCode.NEG_I32; // '\0' 或 'i' }; } - /* =================== 类型推断与操作符匹配 =================== */ + /* ────────────────── 比较运算(已适配 long) ────────────────── */ - /** - * 递归推断单个表达式节点的类型后缀(b/s/l/f/d)。 - * 对于二元表达式,将左右两侧的类型自动提升合并,遵循优先级顺序:d > f > l > s > b > '\0'。 - * - * @param node 表达式节点 - * @return 类型后缀字符,b/s/l/f/d 或 '\0' - */ - private static char typeChar(ExpressionNode node) { - // 字面量节点,直接判断最后一位 - if (node instanceof NumberLiteralNode(String value)) { - char last = Character.toLowerCase(value.charAt(value.length() - 1)); - return switch (last) { - case 'b', 's', 'l', 'f', 'd' -> last; - default -> looksLikeFloat(value) ? 'd' : '\0'; - }; - } - // 二元表达式,递归判断左右子节点 - if (node instanceof BinaryExpressionNode bin) { - char l = typeChar(bin.left()); - char r = typeChar(bin.right()); - return maxTypeChar(l, r); - } - // 其他情况(如变量节点),暂不处理,默认返回 '\0' - return '\0'; + /** 判断给定字符串是否是比较运算符(==, !=, <, >, <=, >=)。 */ + public static boolean isComparisonOperator(String op) { + return ComparisonUtils.isComparisonOperator(op); } /** - * 推断两个表达式节点合并后的类型后缀。 - * 返回优先级更高的类型后缀字符。 - * - * @param left 左表达式节点 - * @param right 右表达式节点 - * @return 合并后类型的后缀字符 + * 兼容旧调用:仅凭操作符返回 int32 比较指令。 */ + public static IROpCode cmpOp(String op) { + return IROpCodeMappings.CMP_I32.get(op); // 旧逻辑:一律 i32 + } + + /** + * 推荐调用:根据左右表达式类型自动选择 int / long 比较指令。 + */ + public static IROpCode cmpOp(String op, ExpressionNode left, ExpressionNode right) { + return ComparisonUtils.cmpOp(op, left, right); + } + + /* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */ + + /** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */ + private static char typeChar(ExpressionNode node) { + if (node instanceof NumberLiteralNode(String value)) { + char last = Character.toLowerCase(value.charAt(value.length() - 1)); + return switch (last) { + case 'b','s','i','l','f','d' -> last; + default -> looksLikeFloat(value) ? 'd' : '\0'; + }; + } + if (node instanceof BinaryExpressionNode bin) { + return maxTypeChar(typeChar(bin.left()), typeChar(bin.right())); + } + return '\0'; // 变量等暂不处理 + } + + /** 合并两侧表达式的类型后缀。 */ public static char resolveSuffix(ExpressionNode left, ExpressionNode right) { return maxTypeChar(typeChar(left), typeChar(right)); } - /** - * 在两个类型后缀中选取精度更高的一个。 - * 优先级依次为:d > f > l > s > b > '\0' - * - * @param l 左类型后缀 - * @param r 右类型后缀 - * @return 更高优先级的类型后缀字符 - */ + /** 类型优先级:d > f > l > i > s > b > '\0' */ private static char maxTypeChar(char l, char r) { if (l == 'd' || r == 'd') return 'd'; if (l == 'f' || r == 'f') return 'f'; if (l == 'l' || r == 'l') return 'l'; + if (l == 'i' || r == 'i') return 'i'; if (l == 's' || r == 's') return 's'; if (l == 'b' || r == 'b') return 'b'; return '\0'; } /** - * 判断给定字符串是否为比较运算符(如 >, <, == 等)。 - * - * @param op 操作符字符串 - * @return 如果是比较操作符返回 true,否则返回 false - */ - public static boolean isComparisonOperator(String op) { - return IROpCodeMappings.CMP.containsKey(op); - } - - /** - * 获取比较操作符对应的中间表示操作码(IROpCode)。 - * - * @param op 比较操作符字符串 - * @return 对应的 IROpCode,如果不存在则返回 null - */ - public static IROpCode cmpOp(String op) { - return IROpCodeMappings.CMP.get(op); - } - - /** - * 根据操作符和两侧表达式自动选择正确的 IROpCode。 - * 首先根据参与表达式类型推断后缀,若无法推断则回退到函数默认类型, - * 还无法推断则默认使用 i32(32位整型)。 - * - * @param op 操作符字符串,如 "+" - * @param left 左侧表达式节点 - * @param right 右侧表达式节点 - * @return 匹配的 IROpCode,如果不存在则返回 null + * 根据操作符和两侧表达式选择正确的算术 {@link IROpCode}。 */ public static IROpCode resolveOpCode(String op, ExpressionNode left, ExpressionNode right) { - /* 1) 尝试从参与者常量字面量推断 */ + /* 1. 尝试根据字面量推断 */ char suffix = resolveSuffix(left, right); - /* 2) 若无法推断,退回到函数返回类型(DEFAULT_SUFFIX) */ - if (suffix == '\0') { - suffix = DEFAULT_SUFFIX.get(); - } + /* 2. 若失败则使用函数级默认类型 */ + if (suffix == '\0') suffix = DEFAULT_SUFFIX.get(); - /* 3) 再次失败则默认为 i32 */ + /* 3. 仍失败则默认为 int32 */ Map table = switch (suffix) { - case 'b' -> IROpCodeMappings.OP_I8; - case 's' -> IROpCodeMappings.OP_I16; + case 'b' -> IROpCodeMappings.OP_B8; + case 's' -> IROpCodeMappings.OP_S16; + case 'i' -> IROpCodeMappings.OP_I32; case 'l' -> IROpCodeMappings.OP_L64; case 'f' -> IROpCodeMappings.OP_F32; case 'd' -> IROpCodeMappings.OP_D64; @@ -230,13 +183,12 @@ public class ExpressionUtils { return table.get(op); } - /** - * 判断字符串是否为浮点数形式(即包含小数点或科学计数法 e/E)。 - * - * @param digits 数字字符串 - * @return 如果看起来像浮点数则返回 true,否则返回 false - */ + /* ────────────────────────── 工具 ───────────────────────── */ + + /** 是否像浮点字面量(包含 '.' 或 e/E)。 */ private static boolean looksLikeFloat(String digits) { - return digits.indexOf('.') >= 0 || digits.indexOf('e') >= 0 || digits.indexOf('E') >= 0; + return digits.indexOf('.') >= 0 + || digits.indexOf('e') >= 0 + || digits.indexOf('E') >= 0; } } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java index fb2eba0..df7118f 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java @@ -8,13 +8,21 @@ import java.util.Map; * IR 操作码辅助工具。 */ public class IROpCodeUtils { - private static final Map INVERT = Map.of( - IROpCode.CMP_LEQ, IROpCode.CMP_LNE, - IROpCode.CMP_LNE, IROpCode.CMP_LEQ, - IROpCode.CMP_LLT, IROpCode.CMP_LGE, - IROpCode.CMP_LGE, IROpCode.CMP_LLT, - IROpCode.CMP_LGT, IROpCode.CMP_LLE, - IROpCode.CMP_LLE, IROpCode.CMP_LGT + private static final Map INVERT = Map.ofEntries( + // 32-bit + Map.entry(IROpCode.CMP_EQ, IROpCode.CMP_NE), + Map.entry(IROpCode.CMP_NE, IROpCode.CMP_EQ), + Map.entry(IROpCode.CMP_LT, IROpCode.CMP_GE), + Map.entry(IROpCode.CMP_GE, IROpCode.CMP_LT), + Map.entry(IROpCode.CMP_GT, IROpCode.CMP_LE), + Map.entry(IROpCode.CMP_LE, IROpCode.CMP_GT), + // 64-bit + Map.entry(IROpCode.CMP_LEQ, IROpCode.CMP_LNE), + Map.entry(IROpCode.CMP_LNE, IROpCode.CMP_LEQ), + Map.entry(IROpCode.CMP_LLT, IROpCode.CMP_LGE), + Map.entry(IROpCode.CMP_LGE, IROpCode.CMP_LLT), + Map.entry(IROpCode.CMP_LGT, IROpCode.CMP_LLE), + Map.entry(IROpCode.CMP_LLE, IROpCode.CMP_LGT) ); /**