docs: 优化 ExpressionUtils 的代码注释
This commit is contained in:
parent
099f4f934c
commit
e7d7e7f96f
@ -12,33 +12,46 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 表达式分析与运算符辅助工具类。
|
||||
*
|
||||
* <p>主要功能:</p>
|
||||
* <ul>
|
||||
* <li>字面量常量的解析与类型推断</li>
|
||||
* <li>自动匹配算术/比较操作码</li>
|
||||
* <li>表达式类型合并与提升</li>
|
||||
* </ul>
|
||||
* 表达式分析与操作符选择工具类。
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* - 解析字面量常量,自动推断类型
|
||||
* - 自动匹配并选择适合的算术/比较操作码
|
||||
* - 表达式类型的合并与类型提升
|
||||
* - 支持线程隔离的函数级默认类型后缀
|
||||
*/
|
||||
public final class ExpressionUtils {
|
||||
|
||||
private ExpressionUtils() {}
|
||||
|
||||
/* ────────────────── 线程级默认类型后缀 ────────────────── */
|
||||
// ───────────── 线程级默认类型后缀 ─────────────
|
||||
|
||||
/** 默认类型后缀(如当前函数返回类型),线程隔离。 */
|
||||
/**
|
||||
* 当前线程的默认类型后缀(如当前函数返回类型等),用于类型推断兜底。
|
||||
*/
|
||||
private static final ThreadLocal<Character> DEFAULT_SUFFIX =
|
||||
ThreadLocal.withInitial(() -> '\0');
|
||||
|
||||
/**
|
||||
* 设置当前线程的默认类型后缀。
|
||||
*
|
||||
* @param suffix 类型后缀字符(b/s/i/l/f/d),'\0'表示无
|
||||
*/
|
||||
public static void setDefaultSuffix(char suffix) { DEFAULT_SUFFIX.set(suffix); }
|
||||
|
||||
/**
|
||||
* 清除当前线程的默认类型后缀,重置为无。
|
||||
*/
|
||||
public static void clearDefaultSuffix() { DEFAULT_SUFFIX.set('\0'); }
|
||||
|
||||
/* ───────────────────── 字面量 & 常量 ───────────────────── */
|
||||
// ───────────── 字面量常量解析 ─────────────
|
||||
|
||||
/**
|
||||
* 解析整数字面量字符串,自动去除类型后缀(b/s/l/f/d/B/S/L/F/D),并转换为 int。
|
||||
* 安全解析整数字面量字符串,自动去除单字符类型后缀(b/s/l/f/d,大小写均可),并转换为 int。
|
||||
*
|
||||
* @param literal 字面量字符串
|
||||
* @return 字面量对应的 int 数值
|
||||
* @throws NumberFormatException 如果字面量无法转换为整数
|
||||
*/
|
||||
public static int parseIntSafely(String literal) {
|
||||
String digits = literal.replaceAll("[bslfdBSDLF]$", "");
|
||||
@ -46,8 +59,14 @@ public final class ExpressionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数字字面量字符串自动判断类型,生成对应类型的 {@link IRConstant}。
|
||||
* 支持 b/s/l/f/d 后缀与浮点格式。
|
||||
* 根据数字字面量字符串推断类型并生成对应的 IRConstant 常量值。
|
||||
* <p>
|
||||
* 支持的字面量后缀有 b/s/l/f/d(大小写均可)。
|
||||
* 无后缀时,优先参考 IRContext 当前变量类型,否则根据字面量格式(含'.'或'e'等)判断为 double,否则为 int。
|
||||
*
|
||||
* @param ctx IRContext,允许参考变量声明类型
|
||||
* @param value 数字字面量字符串
|
||||
* @return 对应类型的 IRConstant 常量
|
||||
*/
|
||||
public static IRConstant buildNumberConstant(IRContext ctx, String value) {
|
||||
char suffix = value.isEmpty() ? '\0'
|
||||
@ -56,7 +75,7 @@ public final class ExpressionUtils {
|
||||
String digits = switch (suffix) {
|
||||
case 'b','s','l','f','d' -> value.substring(0, value.length() - 1);
|
||||
default -> {
|
||||
/* 如果字面量本身没有后缀,则回退到变量目标类型(如声明语句左值) */
|
||||
// 无后缀,优先参考变量类型
|
||||
if (ctx.getVarType() != null) {
|
||||
String t = ctx.getVarType();
|
||||
suffix = switch (t) {
|
||||
@ -73,7 +92,7 @@ public final class ExpressionUtils {
|
||||
}
|
||||
};
|
||||
|
||||
/* 创建常量 */
|
||||
// 生成常量对象
|
||||
return switch (suffix) {
|
||||
case 'b' -> new IRConstant(Byte.parseByte(digits));
|
||||
case 's' -> new IRConstant(Short.parseShort(digits));
|
||||
@ -86,10 +105,13 @@ public final class ExpressionUtils {
|
||||
};
|
||||
}
|
||||
|
||||
/* ────────────────────── 一元运算 ────────────────────── */
|
||||
// ───────────── 一元运算指令匹配 ─────────────
|
||||
|
||||
/**
|
||||
* 推断一元取负(-)运算应使用的 {@link IROpCode}。
|
||||
* 根据表达式节点的类型后缀,选择对应的取负(-)运算操作码。
|
||||
*
|
||||
* @param operand 操作数表达式
|
||||
* @return 匹配类型的 IROpCode
|
||||
*/
|
||||
public static IROpCode negOp(ExpressionNode operand) {
|
||||
char t = typeChar(operand);
|
||||
@ -99,34 +121,54 @@ public final class ExpressionUtils {
|
||||
case 'l' -> IROpCode.NEG_L64;
|
||||
case 'f' -> IROpCode.NEG_F32;
|
||||
case 'd' -> IROpCode.NEG_D64;
|
||||
default -> IROpCode.NEG_I32; // '\0' 或 'i'
|
||||
default -> IROpCode.NEG_I32; // 无法推断或为 int
|
||||
};
|
||||
}
|
||||
|
||||
/* ────────────────── 比较运算(已适配 long) ────────────────── */
|
||||
// ───────────── 比较运算相关 ─────────────
|
||||
|
||||
/** 判断给定字符串是否是比较运算符(==, !=, <, >, <=, >=)。 */
|
||||
/**
|
||||
* 判断给定字符串是否为支持的比较运算符(==, !=, <, >, <=, >=)。
|
||||
*
|
||||
* @param op 操作符字符串
|
||||
* @return 若为比较运算符返回 true,否则返回 false
|
||||
*/
|
||||
public static boolean isComparisonOperator(String op) {
|
||||
return ComparisonUtils.isComparisonOperator(op);
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧调用:仅凭操作符返回 <em>int32</em> 比较指令。
|
||||
* 兼容旧逻辑:仅凭操作符直接返回 int32 比较指令。
|
||||
*
|
||||
* @param op 比较操作符
|
||||
* @return int32 类型的比较操作码
|
||||
*/
|
||||
public static IROpCode cmpOp(String op) {
|
||||
return IROpCodeMappings.CMP_I32.get(op); // 旧逻辑:一律 i32
|
||||
return IROpCodeMappings.CMP_I32.get(op);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推荐调用:根据左右表达式类型自动选择 int / long 比较指令。
|
||||
* 推荐调用:根据左右表达式类型自动选择 int/long/float/double 等合适的比较操作码。
|
||||
*
|
||||
* @param variables 变量名到类型的映射
|
||||
* @param op 比较符号
|
||||
* @param left 左操作数表达式
|
||||
* @param right 右操作数表达式
|
||||
* @return 匹配类型的比较操作码
|
||||
*/
|
||||
public static IROpCode cmpOp(Map<String, String> variables, String op, ExpressionNode left, ExpressionNode right) {
|
||||
return ComparisonUtils.cmpOp(variables, op, left, right);
|
||||
}
|
||||
|
||||
/* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */
|
||||
// ───────────── 类型推断与算术操作码匹配 ─────────────
|
||||
|
||||
/** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */
|
||||
/**
|
||||
* 递归推断表达式节点的类型后缀(b/s/i/l/f/d)。
|
||||
* 优先从字面量和二元表达式合并类型,变量节点暂不处理,返回 '\0'。
|
||||
*
|
||||
* @param node 表达式节点
|
||||
* @return 推断的类型后缀(小写),不确定时返回 '\0'
|
||||
*/
|
||||
private static char typeChar(ExpressionNode node) {
|
||||
if (node instanceof NumberLiteralNode(String value, NodeContext _)) {
|
||||
char last = Character.toLowerCase(value.charAt(value.length() - 1));
|
||||
@ -141,12 +183,25 @@ public final class ExpressionUtils {
|
||||
return '\0'; // 变量等暂不处理
|
||||
}
|
||||
|
||||
/** 合并两侧表达式的类型后缀。 */
|
||||
/**
|
||||
* 合并两个表达式节点的类型后缀,按照 d > f > l > i > s > b > '\0' 优先级返回最宽类型。
|
||||
*
|
||||
* @param left 左表达式
|
||||
* @param right 右表达式
|
||||
* @return 合并后的类型后缀
|
||||
*/
|
||||
public static char resolveSuffix(ExpressionNode left, ExpressionNode right) {
|
||||
return maxTypeChar(typeChar(left), typeChar(right));
|
||||
}
|
||||
|
||||
/** 类型优先级:d > f > l > i > s > b > '\0' */
|
||||
/**
|
||||
* 返回两个类型后缀中的最大类型(宽度优先)。
|
||||
* 优先级:d > f > l > i > s > b > '\0'
|
||||
*
|
||||
* @param l 类型后缀1
|
||||
* @param r 类型后缀2
|
||||
* @return 最宽类型后缀
|
||||
*/
|
||||
private static char maxTypeChar(char l, char r) {
|
||||
if (l == 'd' || r == 'd') return 'd';
|
||||
if (l == 'f' || r == 'f') return 'f';
|
||||
@ -158,35 +213,42 @@ public final class ExpressionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据操作符和两侧表达式选择正确的算术 {@link IROpCode}。
|
||||
* 根据操作符和两侧表达式,选择匹配的算术操作码(IROpCode)。
|
||||
* <p>
|
||||
* 类型推断优先使用左右表达式的类型后缀,推断失败时回退为线程级默认类型后缀,再失败则默认为 int32。
|
||||
*
|
||||
* @param op 算术操作符
|
||||
* @param left 左表达式
|
||||
* @param right 右表达式
|
||||
* @return 匹配类型的 IROpCode
|
||||
*/
|
||||
public static IROpCode resolveOpCode(String op,
|
||||
ExpressionNode left,
|
||||
ExpressionNode right) {
|
||||
|
||||
/* 1. 尝试根据字面量推断 */
|
||||
// 1. 优先根据表达式类型推断
|
||||
char suffix = resolveSuffix(left, right);
|
||||
|
||||
/* 2. 若失败则使用函数级默认类型 */
|
||||
// 2. 推断失败则使用线程默认类型
|
||||
if (suffix == '\0') suffix = DEFAULT_SUFFIX.get();
|
||||
|
||||
/* 3. 仍失败则默认为 int32 */
|
||||
// 3. 仍失败则默认为 int32
|
||||
Map<String, IROpCode> table = switch (suffix) {
|
||||
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;
|
||||
default -> IROpCodeMappings.OP_I32;
|
||||
};
|
||||
|
||||
return table.get(op);
|
||||
}
|
||||
|
||||
/* ────────────────────────── 工具 ───────────────────────── */
|
||||
// ───────────── 字符串辅助工具 ─────────────
|
||||
|
||||
/** 是否像浮点字面量(包含 '.' 或 e/E)。 */
|
||||
/**
|
||||
* 判断字面量字符串是否看起来像浮点数(包含小数点或 e/E 科学计数法)。
|
||||
*
|
||||
* @param digits 字面量字符串
|
||||
* @return 是浮点格式则返回 true
|
||||
*/
|
||||
private static boolean looksLikeFloat(String digits) {
|
||||
return digits.indexOf('.') >= 0
|
||||
|| digits.indexOf('e') >= 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user