!32 feat: 补充基本数值类型转换指令
Merge pull request !32 from zhangxun/feature/full-type-conversion-support
This commit is contained in:
commit
30573a4e45
@ -3,7 +3,7 @@
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
|
||||
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.cli.SnowCLI" />
|
||||
<module name="Snow" />
|
||||
<option name="PROGRAM_PARAMETERS" value="compile run -d playground/Demo11 -o target/Demo11" />
|
||||
<option name="PROGRAM_PARAMETERS" value="compile run -d playground/Demo/Demo11 -o target/Demo11" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
|
||||
|
||||
10
.run/Demo13.run.xml
Normal file
10
.run/Demo13.run.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Demo13" type="Application" factoryName="Application" folderName="Demo">
|
||||
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.cli.SnowCLI" />
|
||||
<module name="Snow" />
|
||||
<option name="PROGRAM_PARAMETERS" value="compile run -d playground/Demo/Demo13 -o target/Demo13" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@ -3,6 +3,9 @@
|
||||
<toRun name="Demo1" type="Application" />
|
||||
<toRun name="Demo10" type="Application" />
|
||||
<toRun name="Demo11" type="Application" />
|
||||
<toRun name="Demo11" type="Application" />
|
||||
<toRun name="Demo12" type="Application" />
|
||||
<toRun name="Demo13" type="Application" />
|
||||
<toRun name="Demo2" type="Application" />
|
||||
<toRun name="Demo3" type="Application" />
|
||||
<toRun name="Demo4" type="Application" />
|
||||
|
||||
69
playground/Demo/Demo13/Main.snow
Normal file
69
playground/Demo/Demo13/Main.snow
Normal file
@ -0,0 +1,69 @@
|
||||
module: Main
|
||||
function: main
|
||||
return_type: int
|
||||
body:
|
||||
5 == 7
|
||||
5 == 7s
|
||||
5 == 7b
|
||||
5 == 7l
|
||||
5 == 7f
|
||||
5 == 7d
|
||||
|
||||
5b == 5b
|
||||
5b == 5s
|
||||
5b == 5l
|
||||
5b == 5f
|
||||
5b == 5d
|
||||
|
||||
5s == 5s
|
||||
5s == 5l
|
||||
5s == 5f
|
||||
5s == 5d
|
||||
|
||||
5l == 5l
|
||||
5l == 5f
|
||||
5l == 5d
|
||||
|
||||
5f == 5f
|
||||
5f == 5d
|
||||
|
||||
5d == 5d
|
||||
|
||||
declare b: byte = 8b
|
||||
declare s: short = 8s
|
||||
declare i: int = 8
|
||||
declare l: long = 8l
|
||||
declare f: float = 8f
|
||||
declare d: double = 8d
|
||||
|
||||
b == b
|
||||
b == s
|
||||
b == i
|
||||
b == l
|
||||
b == f
|
||||
b == d
|
||||
|
||||
s == s
|
||||
s == i
|
||||
s == l
|
||||
s == f
|
||||
s == d
|
||||
|
||||
i == i
|
||||
i == l
|
||||
i == f
|
||||
i == d
|
||||
|
||||
l == l
|
||||
l == f
|
||||
l == d
|
||||
|
||||
f == f
|
||||
f == d
|
||||
|
||||
d == d
|
||||
|
||||
return 65537
|
||||
end body
|
||||
end function
|
||||
end module
|
||||
@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
||||
import org.jcnc.snow.compiler.backend.core.InstructionGenerator;
|
||||
import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
|
||||
import org.jcnc.snow.compiler.backend.utils.OpHelper;
|
||||
import org.jcnc.snow.compiler.backend.utils.TypePromoteUtils;
|
||||
import org.jcnc.snow.compiler.ir.core.IRValue;
|
||||
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
|
||||
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
||||
@ -41,38 +42,12 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
||||
return fn + "$" + tag + "$" + COUNTER.getAndIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型优先级:D > F > L > I > S > B
|
||||
*/
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回优先级更高的类型字符
|
||||
*/
|
||||
private static char promote(char a, char b) {
|
||||
return rank(a) >= rank(b) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单字符转字符串
|
||||
*/
|
||||
private static String str(char p) {
|
||||
return String.valueOf(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断常量值是否等于 0。
|
||||
* 仅支持 Java 原生数值类型。
|
||||
*
|
||||
* @param v 常量值
|
||||
* @return 等于 0 返回 true,否则 false
|
||||
*/
|
||||
private static boolean isZero(Object v) {
|
||||
if (v == null) return false;
|
||||
@ -87,31 +62,6 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取从类型 {@code from} 到 {@code to} 的转换指令名。
|
||||
* 相同类型或无显式转换需求返回 {@code null}。
|
||||
*/
|
||||
private static String convert(char from, char to) {
|
||||
if (from == to) return null;
|
||||
return switch ("" + from + to) {
|
||||
case "IL" -> "I2L";
|
||||
case "ID" -> "I2D";
|
||||
case "IF" -> "I2F";
|
||||
case "LI" -> "L2I";
|
||||
case "LD" -> "L2D";
|
||||
case "LF" -> "L2F";
|
||||
case "FI" -> "F2I";
|
||||
case "FL" -> "F2L";
|
||||
case "FD" -> "F2D";
|
||||
case "DI" -> "D2I";
|
||||
case "DL" -> "D2L";
|
||||
case "DF" -> "D2F";
|
||||
case "SI" -> "S2I";
|
||||
case "BI" -> "B2I";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/* -------------------- 接口实现 -------------------- */
|
||||
|
||||
@Override
|
||||
@ -161,16 +111,16 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
||||
char lType = out.getSlotType(lSlot); // 未登记默认 'I'
|
||||
char rType = out.getSlotType(rSlot);
|
||||
|
||||
char tType = promote(lType, rType); // 类型提升结果
|
||||
String tPre = str(tType);
|
||||
char tType = TypePromoteUtils.promote(lType, rType); // 类型提升结果
|
||||
String tPre = TypePromoteUtils.str(tType);
|
||||
|
||||
/* ---------- 2. 加载并做类型转换 ---------- */
|
||||
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + lSlot);
|
||||
String cvt = convert(lType, tType);
|
||||
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + lSlot);
|
||||
String cvt = TypePromoteUtils.convert(lType, tType);
|
||||
if (cvt != null) out.emit(OpHelper.opcode(cvt));
|
||||
|
||||
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rSlot);
|
||||
cvt = convert(rType, tType);
|
||||
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rSlot);
|
||||
cvt = TypePromoteUtils.convert(rType, tType);
|
||||
if (cvt != null) out.emit(OpHelper.opcode(cvt));
|
||||
|
||||
/* ---------- 3. 区分算术 / 比较 ---------- */
|
||||
@ -186,7 +136,7 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
||||
}
|
||||
|
||||
/* === 3-B. CMP_* —— 生成布尔结果 === */
|
||||
String branchOp = OpHelper.opcode(IROpCodeMapper.toVMOp(ins.op())); // IC_E / IC_NE …
|
||||
String branchOp = OpHelper.opcode(IROpCodeMapper.toVMOp(ins.op())); // I_CE / I_CNE …
|
||||
String lblTrue = fresh(currentFn, "true");
|
||||
String lblEnd = fresh(currentFn, "end");
|
||||
|
||||
|
||||
@ -4,20 +4,21 @@ import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
|
||||
import org.jcnc.snow.compiler.backend.utils.OpHelper;
|
||||
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
||||
import org.jcnc.snow.compiler.backend.core.InstructionGenerator;
|
||||
import org.jcnc.snow.compiler.backend.utils.TypePromoteUtils;
|
||||
import org.jcnc.snow.compiler.ir.instruction.IRCompareJumpInstruction;
|
||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <b>条件比较跳转指令生成器</b>
|
||||
* 条件比较跳转指令生成器
|
||||
* <p>
|
||||
* 该类实现了 {@link InstructionGenerator} 接口,
|
||||
* 负责将 IR 中的 {@link IRCompareJumpInstruction}(条件比较并跳转指令)
|
||||
* 转换为目标虚拟机(VM)可执行的指令序列。
|
||||
* </p>
|
||||
*
|
||||
* <b>主要功能</b>
|
||||
* 主要功能
|
||||
* <ul>
|
||||
* <li>根据 IR 比较指令左右操作数的类型,自动进行类型提升与转换</li>
|
||||
* <li>生成相应的 VM 加载、类型转换、比较与跳转指令</li>
|
||||
@ -36,85 +37,6 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
||||
return IRCompareJumpInstruction.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* <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 宽度更高的类型标记字符
|
||||
*/
|
||||
private static char promote(char a, char b) {
|
||||
return rank(a) >= rank(b) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单字符类型标记转字符串。
|
||||
*
|
||||
* @param p 类型标记字符
|
||||
* @return 类型字符串
|
||||
*/
|
||||
private static String str(char p) {
|
||||
return String.valueOf(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 {@code from → to} 的类型转换指令名(如不需转换则返回 {@code null})。
|
||||
* <p>
|
||||
* 仅覆盖目前常见的整数与浮点类型提升与转换,后续有新类型可补充。
|
||||
* </p>
|
||||
*
|
||||
* @param from 源类型标记字符
|
||||
* @param to 目标类型标记字符
|
||||
* @return 转换指令名,如“L2I”;无转换返回 {@code null}
|
||||
*/
|
||||
private static String convert(char from, char to) {
|
||||
if (from == to) return null;
|
||||
return switch ("" + from + to) {
|
||||
case "IL" -> "I2L";
|
||||
case "ID" -> "I2D";
|
||||
case "IF" -> "I2F";
|
||||
case "LI" -> "L2I";
|
||||
case "LD" -> "L2D";
|
||||
case "LF" -> "L2F";
|
||||
case "FI" -> "F2I";
|
||||
case "FL" -> "F2L";
|
||||
case "FD" -> "F2D";
|
||||
case "DI" -> "D2I";
|
||||
case "DL" -> "D2L";
|
||||
case "DF" -> "D2F";
|
||||
case "SI" -> "S2I";
|
||||
case "BI" -> "B2I";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 IR 条件比较跳转指令的 VM 指令序列。
|
||||
* <ol>
|
||||
@ -138,21 +60,21 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
||||
// 1. 获取左右操作数的槽位与静态类型
|
||||
int leftSlot = slotMap.get(ins.left());
|
||||
int rightSlot = slotMap.get(ins.right());
|
||||
char lType = out.getSlotType(leftSlot); // 若未登记则默认 'I'
|
||||
char lType = out.getSlotType(leftSlot);
|
||||
char rType = out.getSlotType(rightSlot);
|
||||
char tType = promote(lType, rType); // 公共类型提升
|
||||
char tType = TypePromoteUtils.promote(lType, rType); // 公共类型提升
|
||||
|
||||
// 2. 加载左右操作数并按需类型转换
|
||||
// 左操作数
|
||||
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + leftSlot);
|
||||
String cvt = convert(lType, tType);
|
||||
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + leftSlot);
|
||||
String cvt = TypePromoteUtils.convert(lType, tType);
|
||||
if (cvt != null) {
|
||||
out.emit(OpHelper.opcode(cvt));
|
||||
}
|
||||
|
||||
// 右操作数
|
||||
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rightSlot);
|
||||
cvt = convert(rType, tType);
|
||||
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rightSlot);
|
||||
cvt = TypePromoteUtils.convert(rType, tType);
|
||||
if (cvt != null) {
|
||||
out.emit(OpHelper.opcode(cvt));
|
||||
}
|
||||
@ -160,12 +82,12 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
||||
// 3. 选择正确的比较指令前缀
|
||||
String cmpOp = IROpCodeMapper.toVMOp(ins.op());
|
||||
/*
|
||||
* 指令前缀(如 int 类型要用 IC_*, long 类型要用 LC_*)
|
||||
* 指令前缀(如 int 类型要用 I_C*, long 类型要用 L_C*)
|
||||
*/
|
||||
if (tType == 'I' && cmpOp.startsWith("LC_")) {
|
||||
cmpOp = "IC_" + cmpOp.substring(3);
|
||||
} else if (tType == 'L' && cmpOp.startsWith("IC_")) {
|
||||
cmpOp = "LC_" + cmpOp.substring(3);
|
||||
if (tType == 'I' && cmpOp.startsWith("L_C")) {
|
||||
cmpOp = "I_C" + cmpOp.substring(3);
|
||||
} else if (tType == 'L' && cmpOp.startsWith("I_C")) {
|
||||
cmpOp = "L_C" + cmpOp.substring(3);
|
||||
}
|
||||
|
||||
// 4. 发出比较与跳转指令
|
||||
|
||||
@ -82,34 +82,66 @@ public final class IROpCodeMapper {
|
||||
opcodeMap.put(IROpCode.NEG_D64, "D_NEG");
|
||||
|
||||
// 比较运算映射
|
||||
// 整形32位比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_IEQ, "IC_E"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_INE, "IC_NE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_ILT, "IC_L"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_IGT, "IC_G"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_ILE, "IC_LE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_IGE, "IC_GE"); // 大于等于
|
||||
// 8位整数比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_BEQ, "B_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_BNE, "B_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_BLT, "B_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_BGT, "B_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_BLE, "B_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_BGE, "B_CGE"); // 大于等于
|
||||
|
||||
// 整形64位比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_LEQ, "LC_E"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_LNE, "LC_NE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_LLT, "LC_L"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_LGT, "LC_G"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_LLE, "LC_LE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_LGE, "LC_GE"); // 大于等于
|
||||
// 16位整数比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_SEQ, "S_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_SNE, "S_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_SLT, "S_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_SGT, "S_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_SLE, "S_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_SGE, "S_CGE"); // 大于等于
|
||||
|
||||
// 32位整数比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_IEQ, "I_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_INE, "I_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_ILT, "I_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_IGT, "I_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_ILE, "I_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_IGE, "I_CGE"); // 大于等于
|
||||
|
||||
// 64位整数比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_LEQ, "L_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_LNE, "L_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_LLT, "L_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_LGT, "L_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_LLE, "L_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_LGE, "L_CGE"); // 大于等于
|
||||
|
||||
// 32位浮点比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_FEQ, "F_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_FNE, "F_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_FLT, "F_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_FGT, "F_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_FLE, "F_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_FGE, "F_CGE"); // 大于等于
|
||||
|
||||
// 64位浮点比较运算映射
|
||||
opcodeMap.put(IROpCode.CMP_DEQ, "D_CE"); // 相等
|
||||
opcodeMap.put(IROpCode.CMP_DNE, "D_CNE"); // 不等
|
||||
opcodeMap.put(IROpCode.CMP_DLT, "D_CL"); // 小于
|
||||
opcodeMap.put(IROpCode.CMP_DGT, "D_CG"); // 大于
|
||||
opcodeMap.put(IROpCode.CMP_DLE, "D_CLE"); // 小于等于
|
||||
opcodeMap.put(IROpCode.CMP_DGE, "D_CGE"); // 大于等于
|
||||
|
||||
// 加载与存储
|
||||
opcodeMap.put(IROpCode.LOAD, "I_LOAD"); // 加载
|
||||
opcodeMap.put(IROpCode.STORE, "I_STORE"); // 存储
|
||||
opcodeMap.put(IROpCode.CONST, "I_PUSH"); // 常量入栈
|
||||
opcodeMap.put(IROpCode.LOAD, "I_LOAD"); // 加载
|
||||
opcodeMap.put(IROpCode.STORE, "I_STORE"); // 存储
|
||||
opcodeMap.put(IROpCode.CONST, "I_PUSH"); // 常量入栈
|
||||
|
||||
// 跳转与标签
|
||||
opcodeMap.put(IROpCode.JUMP, "JMP"); // 无条件跳转
|
||||
opcodeMap.put(IROpCode.LABEL, "LABEL"); // 标签
|
||||
opcodeMap.put(IROpCode.JUMP, "JMP"); // 无条件跳转
|
||||
opcodeMap.put(IROpCode.LABEL, "LABEL"); // 标签
|
||||
|
||||
// 函数相关
|
||||
opcodeMap.put(IROpCode.CALL, "CALL"); // 调用
|
||||
opcodeMap.put(IROpCode.RET, "RET"); // 返回
|
||||
opcodeMap.put(IROpCode.CALL, "CALL"); // 调用
|
||||
opcodeMap.put(IROpCode.RET, "RET"); // 返回
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -29,108 +29,154 @@ public final class OpHelper {
|
||||
|
||||
static {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("I_ADD", Integer.toString(VMOpCode.I_ADD));
|
||||
map.put("I_SUB", Integer.toString(VMOpCode.I_SUB));
|
||||
map.put("I_MUL", Integer.toString(VMOpCode.I_MUL));
|
||||
map.put("I_DIV", Integer.toString(VMOpCode.I_DIV));
|
||||
map.put("I_MOD", Integer.toString(VMOpCode.I_MOD));
|
||||
map.put("I_INC", Integer.toString(VMOpCode.I_INC));
|
||||
map.put("I_NEG", Integer.toString(VMOpCode.I_NEG));
|
||||
map.put("L_ADD", Integer.toString(VMOpCode.L_ADD));
|
||||
map.put("L_SUB", Integer.toString(VMOpCode.L_SUB));
|
||||
map.put("L_MUL", Integer.toString(VMOpCode.L_MUL));
|
||||
map.put("L_DIV", Integer.toString(VMOpCode.L_DIV));
|
||||
map.put("L_MOD", Integer.toString(VMOpCode.L_MOD));
|
||||
map.put("L_INC", Integer.toString(VMOpCode.L_INC));
|
||||
map.put("L_NEG", Integer.toString(VMOpCode.L_NEG));
|
||||
map.put("S_ADD", Integer.toString(VMOpCode.S_ADD));
|
||||
map.put("S_SUB", Integer.toString(VMOpCode.S_SUB));
|
||||
map.put("S_MUL", Integer.toString(VMOpCode.S_MUL));
|
||||
map.put("S_DIV", Integer.toString(VMOpCode.S_DIV));
|
||||
map.put("S_MOD", Integer.toString(VMOpCode.S_MOD));
|
||||
map.put("S_INC", Integer.toString(VMOpCode.S_INC));
|
||||
map.put("S_NEG", Integer.toString(VMOpCode.S_NEG));
|
||||
map.put("B_ADD", Integer.toString(VMOpCode.B_ADD));
|
||||
map.put("B_SUB", Integer.toString(VMOpCode.B_SUB));
|
||||
map.put("B_MUL", Integer.toString(VMOpCode.B_MUL));
|
||||
map.put("B_DIV", Integer.toString(VMOpCode.B_DIV));
|
||||
map.put("B_MOD", Integer.toString(VMOpCode.B_MOD));
|
||||
map.put("B_INC", Integer.toString(VMOpCode.B_INC));
|
||||
map.put("B_NEG", Integer.toString(VMOpCode.B_NEG));
|
||||
map.put("D_ADD", Integer.toString(VMOpCode.D_ADD));
|
||||
map.put("D_SUB", Integer.toString(VMOpCode.D_SUB));
|
||||
map.put("D_MUL", Integer.toString(VMOpCode.D_MUL));
|
||||
map.put("D_DIV", Integer.toString(VMOpCode.D_DIV));
|
||||
map.put("D_MOD", Integer.toString(VMOpCode.D_MOD));
|
||||
map.put("D_NEG", Integer.toString(VMOpCode.D_NEG));
|
||||
map.put("B_INC", Integer.toString(VMOpCode.B_INC));
|
||||
map.put("B_AND", Integer.toString(VMOpCode.B_AND));
|
||||
map.put("B_OR", Integer.toString(VMOpCode.B_OR));
|
||||
map.put("B_XOR", Integer.toString(VMOpCode.B_XOR));
|
||||
map.put("B_PUSH", Integer.toString(VMOpCode.B_PUSH));
|
||||
map.put("B_LOAD", Integer.toString(VMOpCode.B_LOAD));
|
||||
map.put("B_STORE", Integer.toString(VMOpCode.B_STORE));
|
||||
map.put("B_CE", Integer.toString(VMOpCode.B_CE));
|
||||
map.put("B_CNE", Integer.toString(VMOpCode.B_CNE));
|
||||
map.put("B_CG", Integer.toString(VMOpCode.B_CG));
|
||||
map.put("B_CGE", Integer.toString(VMOpCode.B_CGE));
|
||||
map.put("B_CL", Integer.toString(VMOpCode.B_CL));
|
||||
map.put("B_CLE", Integer.toString(VMOpCode.B_CLE));
|
||||
map.put("S_ADD", Integer.toString(VMOpCode.S_ADD));
|
||||
map.put("S_SUB", Integer.toString(VMOpCode.S_SUB));
|
||||
map.put("S_MUL", Integer.toString(VMOpCode.S_MUL));
|
||||
map.put("S_DIV", Integer.toString(VMOpCode.S_DIV));
|
||||
map.put("S_MOD", Integer.toString(VMOpCode.S_MOD));
|
||||
map.put("S_NEG", Integer.toString(VMOpCode.S_NEG));
|
||||
map.put("S_INC", Integer.toString(VMOpCode.S_INC));
|
||||
map.put("S_AND", Integer.toString(VMOpCode.S_AND));
|
||||
map.put("S_OR", Integer.toString(VMOpCode.S_OR));
|
||||
map.put("S_XOR", Integer.toString(VMOpCode.S_XOR));
|
||||
map.put("S_PUSH", Integer.toString(VMOpCode.S_PUSH));
|
||||
map.put("S_LOAD", Integer.toString(VMOpCode.S_LOAD));
|
||||
map.put("S_STORE", Integer.toString(VMOpCode.S_STORE));
|
||||
map.put("S_CE", Integer.toString(VMOpCode.S_CE));
|
||||
map.put("S_CNE", Integer.toString(VMOpCode.S_CNE));
|
||||
map.put("S_CG", Integer.toString(VMOpCode.S_CG));
|
||||
map.put("S_CGE", Integer.toString(VMOpCode.S_CGE));
|
||||
map.put("S_CL", Integer.toString(VMOpCode.S_CL));
|
||||
map.put("S_CLE", Integer.toString(VMOpCode.S_CLE));
|
||||
map.put("I_ADD", Integer.toString(VMOpCode.I_ADD));
|
||||
map.put("I_SUB", Integer.toString(VMOpCode.I_SUB));
|
||||
map.put("I_MUL", Integer.toString(VMOpCode.I_MUL));
|
||||
map.put("I_DIV", Integer.toString(VMOpCode.I_DIV));
|
||||
map.put("I_MOD", Integer.toString(VMOpCode.I_MOD));
|
||||
map.put("I_NEG", Integer.toString(VMOpCode.I_NEG));
|
||||
map.put("I_INC", Integer.toString(VMOpCode.I_INC));
|
||||
map.put("I_AND", Integer.toString(VMOpCode.I_AND));
|
||||
map.put("I_OR", Integer.toString(VMOpCode.I_OR));
|
||||
map.put("I_XOR", Integer.toString(VMOpCode.I_XOR));
|
||||
map.put("I_PUSH", Integer.toString(VMOpCode.I_PUSH));
|
||||
map.put("I_LOAD", Integer.toString(VMOpCode.I_LOAD));
|
||||
map.put("I_STORE", Integer.toString(VMOpCode.I_STORE));
|
||||
map.put("I_CE", Integer.toString(VMOpCode.I_CE));
|
||||
map.put("I_CNE", Integer.toString(VMOpCode.I_CNE));
|
||||
map.put("I_CG", Integer.toString(VMOpCode.I_CG));
|
||||
map.put("I_CGE", Integer.toString(VMOpCode.I_CGE));
|
||||
map.put("I_CL", Integer.toString(VMOpCode.I_CL));
|
||||
map.put("I_CLE", Integer.toString(VMOpCode.I_CLE));
|
||||
map.put("L_ADD", Integer.toString(VMOpCode.L_ADD));
|
||||
map.put("L_SUB", Integer.toString(VMOpCode.L_SUB));
|
||||
map.put("L_MUL", Integer.toString(VMOpCode.L_MUL));
|
||||
map.put("L_DIV", Integer.toString(VMOpCode.L_DIV));
|
||||
map.put("L_MOD", Integer.toString(VMOpCode.L_MOD));
|
||||
map.put("L_NEG", Integer.toString(VMOpCode.L_NEG));
|
||||
map.put("L_INC", Integer.toString(VMOpCode.L_INC));
|
||||
map.put("L_AND", Integer.toString(VMOpCode.L_AND));
|
||||
map.put("L_OR", Integer.toString(VMOpCode.L_OR));
|
||||
map.put("L_XOR", Integer.toString(VMOpCode.L_XOR));
|
||||
map.put("L_PUSH", Integer.toString(VMOpCode.L_PUSH));
|
||||
map.put("L_LOAD", Integer.toString(VMOpCode.L_LOAD));
|
||||
map.put("L_STORE", Integer.toString(VMOpCode.L_STORE));
|
||||
map.put("L_CE", Integer.toString(VMOpCode.L_CE));
|
||||
map.put("L_CNE", Integer.toString(VMOpCode.L_CNE));
|
||||
map.put("L_CG", Integer.toString(VMOpCode.L_CG));
|
||||
map.put("L_CGE", Integer.toString(VMOpCode.L_CGE));
|
||||
map.put("L_CL", Integer.toString(VMOpCode.L_CL));
|
||||
map.put("L_CLE", Integer.toString(VMOpCode.L_CLE));
|
||||
map.put("F_ADD", Integer.toString(VMOpCode.F_ADD));
|
||||
map.put("F_SUB", Integer.toString(VMOpCode.F_SUB));
|
||||
map.put("F_MUL", Integer.toString(VMOpCode.F_MUL));
|
||||
map.put("F_DIV", Integer.toString(VMOpCode.F_DIV));
|
||||
map.put("F_MOD", Integer.toString(VMOpCode.F_MOD));
|
||||
map.put("F_NEG", Integer.toString(VMOpCode.F_NEG));
|
||||
map.put("D_INC", Integer.toString(VMOpCode.D_INC));
|
||||
map.put("F_INC", Integer.toString(VMOpCode.F_INC));
|
||||
map.put("I2L", Integer.toString(VMOpCode.I2L));
|
||||
map.put("I2S", Integer.toString(VMOpCode.I2S));
|
||||
map.put("F_PUSH", Integer.toString(VMOpCode.F_PUSH));
|
||||
map.put("F_LOAD", Integer.toString(VMOpCode.F_LOAD));
|
||||
map.put("F_STORE", Integer.toString(VMOpCode.F_STORE));
|
||||
map.put("F_CE", Integer.toString(VMOpCode.F_CE));
|
||||
map.put("F_CNE", Integer.toString(VMOpCode.F_CNE));
|
||||
map.put("F_CG", Integer.toString(VMOpCode.F_CG));
|
||||
map.put("F_CGE", Integer.toString(VMOpCode.F_CGE));
|
||||
map.put("F_CL", Integer.toString(VMOpCode.F_CL));
|
||||
map.put("F_CLE", Integer.toString(VMOpCode.F_CLE));
|
||||
map.put("D_ADD", Integer.toString(VMOpCode.D_ADD));
|
||||
map.put("D_SUB", Integer.toString(VMOpCode.D_SUB));
|
||||
map.put("D_MUL", Integer.toString(VMOpCode.D_MUL));
|
||||
map.put("D_DIV", Integer.toString(VMOpCode.D_DIV));
|
||||
map.put("D_MOD", Integer.toString(VMOpCode.D_MOD));
|
||||
map.put("D_NEG", Integer.toString(VMOpCode.D_NEG));
|
||||
map.put("D_INC", Integer.toString(VMOpCode.D_INC));
|
||||
map.put("D_PUSH", Integer.toString(VMOpCode.D_PUSH));
|
||||
map.put("D_LOAD", Integer.toString(VMOpCode.D_LOAD));
|
||||
map.put("D_STORE", Integer.toString(VMOpCode.D_STORE));
|
||||
map.put("D_CE", Integer.toString(VMOpCode.D_CE));
|
||||
map.put("D_CNE", Integer.toString(VMOpCode.D_CNE));
|
||||
map.put("D_CG", Integer.toString(VMOpCode.D_CG));
|
||||
map.put("D_CGE", Integer.toString(VMOpCode.D_CGE));
|
||||
map.put("D_CL", Integer.toString(VMOpCode.D_CL));
|
||||
map.put("D_CLE", Integer.toString(VMOpCode.D_CLE));
|
||||
map.put("B2S", Integer.toString(VMOpCode.B2S));
|
||||
map.put("B2I", Integer.toString(VMOpCode.B2I));
|
||||
map.put("B2L", Integer.toString(VMOpCode.B2L));
|
||||
map.put("B2F", Integer.toString(VMOpCode.B2F));
|
||||
map.put("B2D", Integer.toString(VMOpCode.B2D));
|
||||
map.put("S2B", Integer.toString(VMOpCode.S2B));
|
||||
map.put("S2I", Integer.toString(VMOpCode.S2I));
|
||||
map.put("S2L", Integer.toString(VMOpCode.S2L));
|
||||
map.put("S2F", Integer.toString(VMOpCode.S2F));
|
||||
map.put("S2D", Integer.toString(VMOpCode.S2D));
|
||||
map.put("I2B", Integer.toString(VMOpCode.I2B));
|
||||
map.put("I2D", Integer.toString(VMOpCode.I2D));
|
||||
map.put("I2S", Integer.toString(VMOpCode.I2S));
|
||||
map.put("I2L", Integer.toString(VMOpCode.I2L));
|
||||
map.put("I2F", Integer.toString(VMOpCode.I2F));
|
||||
map.put("I2D", Integer.toString(VMOpCode.I2D));
|
||||
map.put("L2B", Integer.toString(VMOpCode.L2B));
|
||||
map.put("L2S", Integer.toString(VMOpCode.L2S));
|
||||
map.put("L2I", Integer.toString(VMOpCode.L2I));
|
||||
map.put("L2D", Integer.toString(VMOpCode.L2D));
|
||||
map.put("L2F", Integer.toString(VMOpCode.L2F));
|
||||
map.put("L2D", Integer.toString(VMOpCode.L2D));
|
||||
map.put("F2B", Integer.toString(VMOpCode.F2B));
|
||||
map.put("F2S", Integer.toString(VMOpCode.F2S));
|
||||
map.put("F2I", Integer.toString(VMOpCode.F2I));
|
||||
map.put("F2L", Integer.toString(VMOpCode.F2L));
|
||||
map.put("F2D", Integer.toString(VMOpCode.F2D));
|
||||
map.put("D2B", Integer.toString(VMOpCode.D2B));
|
||||
map.put("D2S", Integer.toString(VMOpCode.D2S));
|
||||
map.put("D2I", Integer.toString(VMOpCode.D2I));
|
||||
map.put("D2L", Integer.toString(VMOpCode.D2L));
|
||||
map.put("D2F", Integer.toString(VMOpCode.D2F));
|
||||
map.put("S2I", Integer.toString(VMOpCode.S2I));
|
||||
map.put("B2I", Integer.toString(VMOpCode.B2I));
|
||||
map.put("I_AND", Integer.toString(VMOpCode.I_AND));
|
||||
map.put("I_OR", Integer.toString(VMOpCode.I_OR));
|
||||
map.put("I_XOR", Integer.toString(VMOpCode.I_XOR));
|
||||
map.put("L_AND", Integer.toString(VMOpCode.L_AND));
|
||||
map.put("L_OR", Integer.toString(VMOpCode.L_OR));
|
||||
map.put("L_XOR", Integer.toString(VMOpCode.L_XOR));
|
||||
map.put("JUMP", Integer.toString(VMOpCode.JUMP));
|
||||
map.put("IC_E", Integer.toString(VMOpCode.I_CE));
|
||||
map.put("IC_NE", Integer.toString(VMOpCode.I_CNE));
|
||||
map.put("IC_G", Integer.toString(VMOpCode.I_CG));
|
||||
map.put("IC_GE", Integer.toString(VMOpCode.I_CGE));
|
||||
map.put("IC_L", Integer.toString(VMOpCode.I_CL));
|
||||
map.put("IC_LE", Integer.toString(VMOpCode.I_CLE));
|
||||
map.put("LC_E", Integer.toString(VMOpCode.L_CE));
|
||||
map.put("LC_NE", Integer.toString(VMOpCode.L_CNE));
|
||||
map.put("LC_G", Integer.toString(VMOpCode.L_CG));
|
||||
map.put("LC_GE", Integer.toString(VMOpCode.L_CGE));
|
||||
map.put("LC_L", Integer.toString(VMOpCode.L_CL));
|
||||
map.put("LC_LE", Integer.toString(VMOpCode.L_CLE));
|
||||
map.put("I_PUSH", Integer.toString(VMOpCode.I_PUSH));
|
||||
map.put("L_PUSH", Integer.toString(VMOpCode.L_PUSH));
|
||||
map.put("S_PUSH", Integer.toString(VMOpCode.S_PUSH));
|
||||
map.put("B_PUSH", Integer.toString(VMOpCode.B_PUSH));
|
||||
map.put("D_PUSH", Integer.toString(VMOpCode.D_PUSH));
|
||||
map.put("F_PUSH", Integer.toString(VMOpCode.F_PUSH));
|
||||
map.put("POP", Integer.toString(VMOpCode.POP));
|
||||
map.put("DUP", Integer.toString(VMOpCode.DUP));
|
||||
map.put("SWAP", Integer.toString(VMOpCode.SWAP));
|
||||
map.put("I_STORE", Integer.toString(VMOpCode.I_STORE));
|
||||
map.put("L_STORE", Integer.toString(VMOpCode.L_STORE));
|
||||
map.put("S_STORE", Integer.toString(VMOpCode.S_STORE));
|
||||
map.put("B_STORE", Integer.toString(VMOpCode.B_STORE));
|
||||
map.put("D_STORE", Integer.toString(VMOpCode.D_STORE));
|
||||
map.put("F_STORE", Integer.toString(VMOpCode.F_STORE));
|
||||
map.put("I_LOAD", Integer.toString(VMOpCode.I_LOAD));
|
||||
map.put("L_LOAD", Integer.toString(VMOpCode.L_LOAD));
|
||||
map.put("S_LOAD", Integer.toString(VMOpCode.S_LOAD));
|
||||
map.put("B_LOAD", Integer.toString(VMOpCode.B_LOAD));
|
||||
map.put("D_LOAD", Integer.toString(VMOpCode.D_LOAD));
|
||||
map.put("F_LOAD", Integer.toString(VMOpCode.F_LOAD));
|
||||
map.put("MOV", Integer.toString(VMOpCode.MOV));
|
||||
map.put("JUMP", Integer.toString(VMOpCode.JUMP));
|
||||
map.put("CALL", Integer.toString(VMOpCode.CALL));
|
||||
map.put("RET", Integer.toString(VMOpCode.RET));
|
||||
map.put("MOV", Integer.toString(VMOpCode.MOV));
|
||||
map.put("HALT", Integer.toString(VMOpCode.HALT));
|
||||
map.put("SYSCALL", Integer.toString(VMOpCode.SYSCALL));
|
||||
map.put("DEBUG_TRAP", Integer.toString(VMOpCode.DEBUG_TRAP));
|
||||
OPCODE_MAP = Collections.unmodifiableMap(map);
|
||||
|
||||
Map<Integer, String> revmap = new HashMap<>(); // reverse map
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
package org.jcnc.snow.compiler.backend.utils;
|
||||
|
||||
/**
|
||||
* 工具类:提供基本数值类型的提升与类型转换辅助功能。
|
||||
* <p>
|
||||
* 在进行数值类型运算、比较等操作时,低优先级的类型会被提升为高优先级类型参与运算。
|
||||
* 例如 int + long 运算,int 会被提升为 long,最终运算结果类型为 long。
|
||||
* <p>
|
||||
* 类型优先级从高到低依次为:
|
||||
* D(double):6
|
||||
* F(float) :5
|
||||
* L(long) :4
|
||||
* I(int) :3
|
||||
* S(short) :2
|
||||
* B(byte) :1
|
||||
* 未识别类型 :0
|
||||
*/
|
||||
public class TypePromoteUtils {
|
||||
|
||||
/**
|
||||
* 返回数值类型的宽度优先级,数值越大类型越宽。
|
||||
* 类型及优先级映射如下:
|
||||
* D(double): 6
|
||||
* F(float) : 5
|
||||
* L(long) : 4
|
||||
* I(int) : 3
|
||||
* S(short) : 2
|
||||
* B(byte) : 1
|
||||
* 未知类型 : 0
|
||||
*
|
||||
* @param p 类型标记字符(B/S/I/L/F/D)
|
||||
* @return 优先级数值(0 表示未知类型)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将单个字符的类型标记转为字符串。
|
||||
*
|
||||
* @param p 类型标记字符
|
||||
* @return 类型标记的字符串形式
|
||||
*/
|
||||
public static String str(char p) {
|
||||
return String.valueOf(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型转换指令名(例如 "I2L", "F2D"),表示从源类型到目标类型的转换操作。
|
||||
* 如果源类型和目标类型相同,则返回 null,表示无需转换。
|
||||
* <p>
|
||||
* 支持的类型标记字符包括:B(byte)、S(short)、I(int)、L(long)、F(float)、D(double)。
|
||||
* 所有可能的类型转换均已覆盖,如下所示:
|
||||
* B → S/I/L/F/D
|
||||
* S → B/I/L/F/D
|
||||
* I → B/S/L/F/D
|
||||
* L → B/S/I/F/D
|
||||
* F → B/S/I/L/D
|
||||
* D → B/S/I/L/F
|
||||
*
|
||||
* @param from 源类型标记字符
|
||||
* @param to 目标类型标记字符
|
||||
* @return 类型转换指令名(如 "L2I"),如无须转换则返回 null
|
||||
*/
|
||||
public static String convert(char from, char to) {
|
||||
if (from == to) return null;
|
||||
return switch ("" + from + to) {
|
||||
case "BS" -> "B2S";
|
||||
case "BI" -> "B2I";
|
||||
case "BL" -> "B2L";
|
||||
case "BF" -> "B2F";
|
||||
case "BD" -> "B2D";
|
||||
|
||||
case "SB" -> "S2B";
|
||||
case "SI" -> "S2I";
|
||||
case "SL" -> "S2L";
|
||||
case "SF" -> "S2F";
|
||||
case "SD" -> "S2D";
|
||||
|
||||
case "IB" -> "I2B";
|
||||
case "IS" -> "I2S";
|
||||
case "IL" -> "I2L";
|
||||
case "IF" -> "I2F";
|
||||
case "ID" -> "I2D";
|
||||
|
||||
case "LB" -> "L2B";
|
||||
case "LS" -> "L2S";
|
||||
case "LI" -> "L2I";
|
||||
case "LF" -> "L2F";
|
||||
case "LD" -> "L2D";
|
||||
|
||||
case "FB" -> "F2B";
|
||||
case "FS" -> "F2S";
|
||||
case "FI" -> "F2I";
|
||||
case "FL" -> "F2L";
|
||||
case "FD" -> "F2D";
|
||||
|
||||
case "DB" -> "D2B";
|
||||
case "DS" -> "D2S";
|
||||
case "DI" -> "D2I";
|
||||
case "DL" -> "D2L";
|
||||
case "DF" -> "D2F";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -66,21 +66,53 @@ public enum IROpCode {
|
||||
DIV_D64, // 64位浮点除法
|
||||
NEG_D64, // 64位浮点取负
|
||||
|
||||
/* ───── 逻辑与比较运算指令(8位整数:byte) ───── */
|
||||
CMP_BEQ, // 8位整数相等比较:a == b
|
||||
CMP_BNE, // 8位整数不等比较:a != b
|
||||
CMP_BLT, // 8位整数小于比较:a < b
|
||||
CMP_BGT, // 8位整数大于比较:a > b
|
||||
CMP_BLE, // 8位整数小于等于:a <= b
|
||||
CMP_BGE, // 8位整数大于等于:a >= b
|
||||
|
||||
/* ───── 逻辑与比较运算指令(16位整数:int) ───── */
|
||||
CMP_SEQ, // 16位整数相等比较:a == b
|
||||
CMP_SNE, // 16位整数不等比较:a != b
|
||||
CMP_SLT, // 16位整数小于比较:a < b
|
||||
CMP_SGT, // 16位整数大于比较:a > b
|
||||
CMP_SLE, // 16位整数小于等于:a <= b
|
||||
CMP_SGE, // 16位整数大于等于:a >= b
|
||||
|
||||
/* ───── 逻辑与比较运算指令(32位整数:int) ───── */
|
||||
CMP_IEQ, // 32位相等比较:a == b
|
||||
CMP_INE, // 32位不等比较:a != b
|
||||
CMP_ILT, // 32位小于比较:a < b
|
||||
CMP_IGT, // 32位大于比较:a > b
|
||||
CMP_ILE, // 32位小于等于:a <= b
|
||||
CMP_IGE, // 32位大于等于:a >= b
|
||||
CMP_IEQ, // 32位整数相等比较:a == b
|
||||
CMP_INE, // 32位整数不等比较:a != b
|
||||
CMP_ILT, // 32位整数小于比较:a < b
|
||||
CMP_IGT, // 32位整数大于比较:a > b
|
||||
CMP_ILE, // 32位整数小于等于:a <= b
|
||||
CMP_IGE, // 32位整数大于等于:a >= b
|
||||
|
||||
/* ───── 逻辑与比较运算指令(64位整数:long) ───── */
|
||||
CMP_LEQ, // 64位相等比较:a == b
|
||||
CMP_LNE, // 64位不等比较:a != b
|
||||
CMP_LLT, // 64位小于比较:a < b
|
||||
CMP_LGT, // 64位大于比较:a > b
|
||||
CMP_LLE, // 64位小于等于:a <= b
|
||||
CMP_LGE, // 64位大于等于:a >= b
|
||||
CMP_LEQ, // 64位整数相等比较:a == b
|
||||
CMP_LNE, // 64位整数不等比较:a != b
|
||||
CMP_LLT, // 64位整数小于比较:a < b
|
||||
CMP_LGT, // 64位整数大于比较:a > b
|
||||
CMP_LLE, // 64位整数小于等于:a <= b
|
||||
CMP_LGE, // 64位整数大于等于:a >= b
|
||||
|
||||
/* ───── 逻辑与比较运算指令(32位浮点数:float) ───── */
|
||||
CMP_FEQ, // 32位浮点相等比较:a == b
|
||||
CMP_FNE, // 32位浮点不等比较:a != b
|
||||
CMP_FLT, // 32位浮点小于比较:a < b
|
||||
CMP_FGT, // 32位浮点大于比较:a > b
|
||||
CMP_FLE, // 32位浮点小于等于:a <= b
|
||||
CMP_FGE, // 32位浮点大于等于:a >= b
|
||||
|
||||
/* ───── 逻辑与比较运算指令(64位浮点数:double) ───── */
|
||||
CMP_DEQ, // 64位浮点相等比较:a == b
|
||||
CMP_DNE, // 64位浮点不等比较:a != b
|
||||
CMP_DLT, // 64位浮点小于比较:a < b
|
||||
CMP_DGT, // 64位浮点大于比较:a > b
|
||||
CMP_DLE, // 64位浮点小于等于:a <= b
|
||||
CMP_DGE, // 64位浮点大于等于:a >= b
|
||||
|
||||
/* ───── 数据访问与常量操作 ───── */
|
||||
LOAD, // 从内存加载数据至寄存器
|
||||
|
||||
@ -40,6 +40,26 @@ public final class IROpCodeMappings {
|
||||
);
|
||||
|
||||
/* ────── 比较运算符映射 ────── */
|
||||
/** 8-bit(byte)比较 */
|
||||
public static final Map<String, IROpCode> CMP_B8 = Map.of(
|
||||
"==", IROpCode.CMP_BEQ,
|
||||
"!=", IROpCode.CMP_BNE,
|
||||
"<", IROpCode.CMP_BLT,
|
||||
">", IROpCode.CMP_BGT,
|
||||
"<=", IROpCode.CMP_BLE,
|
||||
">=", IROpCode.CMP_BGE
|
||||
);
|
||||
|
||||
/** 16-bit(short)比较 */
|
||||
public static final Map<String, IROpCode> CMP_S16 = Map.of(
|
||||
"==", IROpCode.CMP_SEQ,
|
||||
"!=", IROpCode.CMP_SNE,
|
||||
"<", IROpCode.CMP_SLT,
|
||||
">", IROpCode.CMP_SGT,
|
||||
"<=", IROpCode.CMP_SLE,
|
||||
">=", IROpCode.CMP_SGE
|
||||
);
|
||||
|
||||
/** 32-bit(int)比较 */
|
||||
public static final Map<String, IROpCode> CMP_I32 = Map.of(
|
||||
"==", IROpCode.CMP_IEQ,
|
||||
@ -60,5 +80,23 @@ public final class IROpCodeMappings {
|
||||
">=", IROpCode.CMP_LGE
|
||||
);
|
||||
|
||||
|
||||
/** 32-bit(float)比较 */
|
||||
public static final Map<String, IROpCode> CMP_F32 = Map.of(
|
||||
"==", IROpCode.CMP_FEQ,
|
||||
"!=", IROpCode.CMP_FNE,
|
||||
"<", IROpCode.CMP_FLT,
|
||||
">", IROpCode.CMP_FGT,
|
||||
"<=", IROpCode.CMP_FLE,
|
||||
">=", IROpCode.CMP_FGE
|
||||
);
|
||||
|
||||
/** 64-bit(double)比较 */
|
||||
public static final Map<String, IROpCode> CMP_D64 = Map.of(
|
||||
"==", IROpCode.CMP_DEQ,
|
||||
"!=", IROpCode.CMP_DNE,
|
||||
"<", IROpCode.CMP_DLT,
|
||||
">", IROpCode.CMP_DGT,
|
||||
"<=", IROpCode.CMP_DLE,
|
||||
">=", IROpCode.CMP_DGE
|
||||
);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -9,42 +10,134 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 比较运算辅助工具:
|
||||
* 根据左右操作数类型(目前通过字面量后缀 <code>L/l</code> 判定)选择
|
||||
* 正确的 IR 比较指令,保证 int/long 均能正常运行。
|
||||
* 工具类,用于比较运算相关的类型推断和指令选择。
|
||||
* <p>
|
||||
* 该类主要用于根据左右操作数的静态类型,自动选择正确的 IR 层比较操作码。
|
||||
* 支持自动类型提升,保证 int、long、float、double 等类型的比较均能得到正确的 IR 指令。
|
||||
* </p>
|
||||
*
|
||||
* 类型判定支持:
|
||||
* <ul>
|
||||
* <li>字面量后缀:支持 B/S/I/L/F/D(大小写均可)</li>
|
||||
* <li>浮点数支持:如无后缀但有小数点,视为 double</li>
|
||||
* <li>变量类型:根据传入变量表推断类型,未识别则默认 int</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class ComparisonUtils {
|
||||
private ComparisonUtils() {
|
||||
}
|
||||
private ComparisonUtils() {}
|
||||
|
||||
/**
|
||||
* 判断给定操作符是否为比较运算符
|
||||
* 判断给定字符串是否为受支持的比较运算符(==, !=, <, >, <=, >=)。
|
||||
* 仅检查 int 类型指令表,因所有类型的比较符号集合相同。
|
||||
*
|
||||
* @param op 比较运算符字符串
|
||||
* @return 若为比较运算符返回 true,否则返回 false
|
||||
*/
|
||||
public static boolean isComparisonOperator(String op) {
|
||||
// 两张表 key 完全一致,只需检查一张
|
||||
// 只需查 int 类型表即可
|
||||
return IROpCodeMappings.CMP_I32.containsKey(op);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回符合操作数位宽的比较 IROpCode。
|
||||
* 返回类型宽度优先级(越大代表类型越宽)。类型对应的优先级:
|
||||
* - D (double): 6
|
||||
* - F (float): 5
|
||||
* - L (long): 4
|
||||
* - I (int): 3
|
||||
* - S (short): 2
|
||||
* - B (byte): 1
|
||||
* - 未知类型: 0
|
||||
*
|
||||
* @param op 比较符号(==, !=, <, >, <=, >=)
|
||||
* @param left 左操作数 AST
|
||||
* @param right 右操作数 AST
|
||||
* @param p 类型标记字符
|
||||
* @return 类型优先级数值
|
||||
*/
|
||||
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;
|
||||
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 variables 变量名到类型的映射(如 "a" -> "int")
|
||||
* @param op 比较符号(==, !=, <, >, <=, >=)
|
||||
* @param left 左操作数表达式
|
||||
* @param right 右操作数表达式
|
||||
* @return 适用的比较 IROpCode
|
||||
* @throws IllegalStateException 如果无法推断合适的类型
|
||||
*/
|
||||
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) {
|
||||
/**
|
||||
* 内部工具方法:根据表达式节点和变量表推断类型标记字符。
|
||||
* 字面量支持 B/S/I/L/F/D(大小写均可),浮点数默认 double;
|
||||
* 标识符类型按变量表映射,未知则默认 int。
|
||||
*
|
||||
* @param variables 变量名到类型的映射
|
||||
* @param node 表达式节点
|
||||
* @return 类型标记字符(B/S/I/L/F/D),未知时返回 I
|
||||
*/
|
||||
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'; // 默认 int
|
||||
}
|
||||
return false; // 变量暂不处理(后续可扩展符号表查询)
|
||||
if (node instanceof IdentifierNode(String name, NodeContext _)) {
|
||||
final String type = variables.get(name);
|
||||
if (type != null) {
|
||||
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'; // 默认 int
|
||||
}
|
||||
}
|
||||
|
||||
@ -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(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);
|
||||
}
|
||||
|
||||
/* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */
|
||||
// ───────────── 类型推断与算术操作码匹配 ─────────────
|
||||
|
||||
/** 递归推断单个表达式节点的类型后缀(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
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* B2DCommand Opcode: Represents the type conversion operation from byte8 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to a double64 type.</p>
|
||||
*/
|
||||
public class B2DCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of B2DCommand.
|
||||
*/
|
||||
public B2DCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the byte8 to double64 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
double convertedValue = (byte) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* B2FCommand Opcode: Represents the type conversion operation from byte8 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to a float32 type.</p>
|
||||
*/
|
||||
public class B2FCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of B2FCommand.
|
||||
*/
|
||||
public B2FCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the byte8 to float32 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
float convertedValue = (byte) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to an int32 type to ensure compatibility with integer-based operations.</p>
|
||||
* <p>This opcode is used to widen a byte8 value to an int32 type.</p>
|
||||
*/
|
||||
public class B2ICommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* B2LCommand Opcode: Represents the type conversion operation from byte8 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to a long64 type.</p>
|
||||
*/
|
||||
public class B2LCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of B2LCommand.
|
||||
*/
|
||||
public B2LCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the byte8 to long64 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
long convertedValue = (byte) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* B2SCommand Opcode: Represents the type conversion operation from byte8 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a short16 value.</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to a short16 type.</p>
|
||||
*/
|
||||
public class B2SCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of B2SCommand.
|
||||
*/
|
||||
public B2SCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the byte8 to short16 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
short convertedValue = (byte) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* D2BCommand Opcode: Represents the type conversion operation from double64 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a byte8 type.</p>
|
||||
*/
|
||||
public class D2BCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of D2BCommand.
|
||||
*/
|
||||
public D2BCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the double64 to byte8 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
double value = (double) operandStack.pop();
|
||||
byte convertedValue = (byte) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a float32 type when lower precision floating-point arithmetic is acceptable.</p>
|
||||
* <p>This opcode is used to narrow a double64 value to a float32 type.</p>
|
||||
*/
|
||||
public class D2FCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to an int32 type for further integer-based operations.</p>
|
||||
* <p>This opcode is used to narrow a double64 value to an int32 type.</p>
|
||||
*/
|
||||
public class D2ICommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a long64 type, which can then be used for integer operations.</p>
|
||||
* <p>This opcode is used to narrow a double64 value to a long64 type.</p>
|
||||
*/
|
||||
public class D2LCommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* D2SCommand Opcode: Represents the type conversion operation from double64 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a short16 type.</p>
|
||||
*/
|
||||
public class D2SCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of D2SCommand.
|
||||
*/
|
||||
public D2SCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the double64 to short16 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
double value = (double) operandStack.pop();
|
||||
short convertedValue = (short) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* F2BCommand Opcode: Represents the type conversion operation from float32 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to a byte8 type.</p>
|
||||
*/
|
||||
public class F2BCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of F2BCommand.
|
||||
*/
|
||||
public F2BCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the float32 to byte8 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
float value = (float) operandStack.pop();
|
||||
byte convertedValue = (byte) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to promote a float32 value to a double64 type, thereby increasing precision for floating-point computations.</p>
|
||||
* <p>This opcode is used to promote a float32 value to a double64 type.</p>
|
||||
*/
|
||||
public class F2DCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to an int32 type for further integer operations or comparisons.</p>
|
||||
* <p>This opcode is used to convert a float32 value to an int32 type.</p>
|
||||
*/
|
||||
public class F2ICommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a float32 value to a long64 type for operations requiring a larger numeric range.</p>
|
||||
* <p>This opcode is used to widen a float32 value to a long64 type.</p>
|
||||
*/
|
||||
public class F2LCommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* F2SCommand Opcode: Represents the type conversion operation from float32 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to a short16 type.</p>
|
||||
*/
|
||||
public class F2SCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of F2SCommand.
|
||||
*/
|
||||
public F2SCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the float32 to short16 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
float value = (float) operandStack.pop();
|
||||
short convertedValue = (short) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow an int32 value to a byte8 type when a smaller numeric representation is required.</p>
|
||||
* <p>This opcode is used to narrow an int32 value to a byte8 type.</p>
|
||||
*/
|
||||
public class I2BCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen an int32 value to a double64 type, providing high-precision floating-point calculations.</p>
|
||||
* <p>This opcode is used to widen an int32 value to a double64 type.</p>
|
||||
*/
|
||||
public class I2DCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert an int32 value to a float32 type when floating-point arithmetic is required.</p>
|
||||
* <p>This opcode is used to convert an int32 value to a float32 type.</p>
|
||||
*/
|
||||
public class I2FCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen an int32 value to a long64 type to accommodate larger numeric ranges.</p>
|
||||
* <p>This opcode is commonly used to widen an int32 value to a long64 type.</p>
|
||||
*/
|
||||
public class I2LCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow an int32 value to a short16 type when a smaller data representation is required.</p>
|
||||
* <p>This opcode is typically used to narrow an int32 value to a short16 type.</p>
|
||||
*/
|
||||
public class I2SCommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* L2BCommand Opcode: Represents the type conversion operation from long64 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a byte8 value.</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a long64 value to a byte8 type.</p>
|
||||
*/
|
||||
public class L2BCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of L2BCommand.
|
||||
*/
|
||||
public L2BCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the long64 to byte8 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
long value = (long) operandStack.pop();
|
||||
byte convertedValue = (byte) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.</p>
|
||||
* <p>This opcode is used to widen a long64 value to a double64 type.</p>
|
||||
*/
|
||||
public class L2DCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a long64 value to a float32 type, typically for floating-point arithmetic involving long values.</p>
|
||||
* <p>This opcode is used to convert a long64 value to a float32 type.</p>
|
||||
*/
|
||||
public class L2FCommand implements Command {
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow a long64 value to an int32 type for further integer operations.</p>
|
||||
* <p>This opcode is typically used to narrow a long64 value to an int32 typ.</p>
|
||||
*/
|
||||
public class L2ICommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* L2SCommand Opcode: Represents the type conversion operation from long64 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a short16 value.</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a long64 value to a short16 type.</p>
|
||||
*/
|
||||
public class L2SCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of L2SCommand.
|
||||
*/
|
||||
public L2SCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the long64 to short16 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
long value = (long) operandStack.pop();
|
||||
short convertedValue = (short) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* S2BCommand Opcode: Represents the type conversion operation from short16 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a byte8 value.</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to a byte8 type.</p>
|
||||
*/
|
||||
public class S2BCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of S2BCommand.
|
||||
*/
|
||||
public S2BCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the short16 to byte8 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
short value = (short) operandStack.pop();
|
||||
byte convertedValue = (byte) value;
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* S2DCommand Opcode: Represents the type conversion operation from short16 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to a double64 type.</p>
|
||||
*/
|
||||
public class S2DCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of S2DCommand.
|
||||
*/
|
||||
public S2DCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the short16 to double64 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
double convertedValue = (short) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* S2FCommand Opcode: Represents the type conversion operation from short16 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to a float32 type.</p>
|
||||
*/
|
||||
public class S2FCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of S2FCommand.
|
||||
*/
|
||||
public S2FCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the short16 to float32 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
float convertedValue = (short) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import org.jcnc.snow.vm.module.OperandStack;
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to an int32 type, facilitating subsequent integer arithmetic or comparison operations.</p>
|
||||
* <p>This opcode is used to widen a short16 value to an int32 type.</p>
|
||||
*/
|
||||
public class S2ICommand implements Command {
|
||||
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jcnc.snow.vm.commands.type.conversion;
|
||||
|
||||
import org.jcnc.snow.vm.interfaces.Command;
|
||||
import org.jcnc.snow.vm.module.CallStack;
|
||||
import org.jcnc.snow.vm.module.LocalVariableStore;
|
||||
import org.jcnc.snow.vm.module.OperandStack;
|
||||
|
||||
/**
|
||||
* S2LCommand Opcode: Represents the type conversion operation from short16 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to a long64 type.</p>
|
||||
*/
|
||||
public class S2LCommand implements Command {
|
||||
|
||||
/**
|
||||
* Default constructor for creating an instance of S2LCommand.
|
||||
*/
|
||||
public S2LCommand() {
|
||||
// Empty constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the short16 to long64 conversion operation.
|
||||
*
|
||||
* @param parts The array of instruction parameters, which is not used in this operation.
|
||||
* @param currentPC The current program counter, representing the instruction address.
|
||||
* @param operandStack The operand stack of the virtual machine.
|
||||
* @param localVariableStore The local variable store for managing method-local variables.
|
||||
* @param callStack The call stack of the virtual machine.
|
||||
* @return The updated program counter after execution.
|
||||
*/
|
||||
@Override
|
||||
public int execute(String[] parts, int currentPC, OperandStack operandStack,
|
||||
LocalVariableStore localVariableStore, CallStack callStack) {
|
||||
long convertedValue = (short) operandStack.pop();
|
||||
operandStack.push(convertedValue);
|
||||
return currentPC + 1;
|
||||
}
|
||||
}
|
||||
@ -2043,216 +2043,21 @@ public class VMOpCode {
|
||||
// endregion
|
||||
|
||||
// region Type Conversion (0x00C0-0x00DF)
|
||||
// region Byte8 (0x00C0-0xC4)
|
||||
/**
|
||||
* I2L Opcode: Represents the type conversion operation from int32 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2LCommand} class, which defines its specific execution logic.</p>
|
||||
* B2S Opcode: Represents the type conversion operation from byte8 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen an int32 value to a long64 type to accommodate larger numeric ranges.</p>
|
||||
*/
|
||||
public static final int I2L = 0x00C0;
|
||||
/**
|
||||
* I2S Opcode: Represents the type conversion operation from int32 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a short16 value.</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow an int32 value to a short16 type when a smaller data representation is needed.</p>
|
||||
* <p>This opcode is commonly used to widen a byte8 value to a short16 type.</p>
|
||||
*/
|
||||
public static final int I2S = 0x00C1;
|
||||
/**
|
||||
* I2B Opcode: Represents the type conversion operation from int32 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow an int32 value to a byte8 type, suitable when a smaller numeric type is required.</p>
|
||||
*/
|
||||
public static final int I2B = 0x00C2;
|
||||
/**
|
||||
* I2D Opcode: Represents the type conversion operation from int32 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen an int32 value to a double64 type, providing high-precision floating-point calculations.</p>
|
||||
*/
|
||||
public static final int I2D = 0x00C3;
|
||||
/**
|
||||
* I2F Opcode: Represents the type conversion operation from int32 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert an int32 value to a float32 type when floating-point arithmetic is required.</p>
|
||||
*/
|
||||
public static final int I2F = 0x00C4;
|
||||
/**
|
||||
* L2I Opcode: Represents the type conversion operation from long64 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow a long64 value to an int32 type for further integer operations.</p>
|
||||
*/
|
||||
public static final int L2I = 0x00C5;
|
||||
/**
|
||||
* L2D Opcode: Represents the type conversion operation from long64 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.</p>
|
||||
*/
|
||||
public static final int L2D = 0x00C6;
|
||||
/**
|
||||
* L2F Opcode: Represents the type conversion operation from long64 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a long64 value to a float32 type, typically for floating-point arithmetic involving long values.</p>
|
||||
*/
|
||||
public static final int L2F = 0x00C7;
|
||||
/**
|
||||
* F2I Opcode: Represents the type conversion operation from float32 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to an int32 type for further integer-based operations or comparisons.</p>
|
||||
*/
|
||||
public static final int F2I = 0x00C8;
|
||||
/**
|
||||
* F2L Opcode: Represents the type conversion operation from float32 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a float32 value to a long64 type, which is useful when operations require a larger numeric range.</p>
|
||||
*/
|
||||
public static final int F2L = 0x00C9;
|
||||
/**
|
||||
* F2D Opcode: Represents the type conversion operation from float32 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to promote a float32 value to a double64 type, thereby increasing precision for floating-point computations.</p>
|
||||
*/
|
||||
public static final int F2D = 0x00CA;
|
||||
/**
|
||||
* D2I Opcode: Represents the type conversion operation from double64 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to an int32 type for further integer-based processing.</p>
|
||||
*/
|
||||
public static final int D2I = 0x00CB;
|
||||
/**
|
||||
* D2L Opcode: Represents the type conversion operation from double64 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a long64 value (this may involve truncation).</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a long64 type, which can then be used for integer operations.</p>
|
||||
*/
|
||||
public static final int D2L = 0x00CC;
|
||||
/**
|
||||
* D2F Opcode: Represents the type conversion operation from double64 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a float32 type when lower precision floating-point arithmetic is acceptable.</p>
|
||||
*/
|
||||
public static final int D2F = 0x00CD;
|
||||
/**
|
||||
* S2I Opcode: Represents the type conversion operation from short16 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to an int32 value.</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to an int32 type, facilitating subsequent integer arithmetic or comparison operations.</p>
|
||||
*/
|
||||
public static final int S2I = 0x00CE;
|
||||
public static final int B2S = 0x00C0;
|
||||
/**
|
||||
* B2I Opcode: Represents the type conversion operation from byte8 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2ICommand} class, which defines its specific execution logic.</p>
|
||||
@ -2264,10 +2069,418 @@ public class VMOpCode {
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to an int32 type to ensure compatibility with integer-based operations.</p>
|
||||
* <p>This opcode is commonly used to widen a byte8 value to an int32 type.</p>
|
||||
*/
|
||||
public static final int B2I = 0x00CF;
|
||||
// endregion
|
||||
public static final int B2I = 0x00C1;
|
||||
/**
|
||||
* B2L Opcode: Represents the type conversion operation from byte8 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen a byte8 value to a long64 type.</p>
|
||||
*/
|
||||
public static final int B2L = 0x00C2;
|
||||
/**
|
||||
* B2F Opcode: Represents the type conversion operation from byte8 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a byte8 value to a float32 type.</p>
|
||||
*/
|
||||
public static final int B2F = 0x00C3;
|
||||
/**
|
||||
* B2D Opcode: Represents the type conversion operation from byte8 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link B2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top byte8 value from the operand stack.</li>
|
||||
* <li>Convert the byte8 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a byte8 value to a double64 type.</p>
|
||||
*/
|
||||
public static final int B2D = 0x00C4;
|
||||
// endregion Byte8
|
||||
|
||||
// region Short16 (0x00C5-0xC9)
|
||||
/**
|
||||
* S2B Opcode: Represents the type conversion operation from short16 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a short16 value to a byte8 type.</p>
|
||||
*/
|
||||
public static final int S2B = 0x00C5;
|
||||
/**
|
||||
* S2I Opcode: Represents the type conversion operation from short16 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to an int32 value.</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen a short16 value to an int32 type.</p>
|
||||
*/
|
||||
public static final int S2I = 0x00C6;
|
||||
/**
|
||||
* S2L Opcode: Represents the type conversion operation from short16 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen a short16 value to a long64 type.</p>
|
||||
*/
|
||||
public static final int S2L = 0x00C7;
|
||||
/**
|
||||
* S2F Opcode: Represents the type conversion operation from short16 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a short16 value to a float32 type.</p>
|
||||
*/
|
||||
public static final int S2F = 0x00C8;
|
||||
/**
|
||||
* S2D Opcode: Represents the type conversion operation from short16 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link S2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top short16 value from the operand stack.</li>
|
||||
* <li>Convert the short16 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a short16 value to a double64 type.</p>
|
||||
*/
|
||||
public static final int S2D = 0x00C9;
|
||||
// endregion Short16
|
||||
|
||||
// region Int32 (0x00CA-0xCE)
|
||||
/**
|
||||
* I2B Opcode: Represents the type conversion operation from int32 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow an int32 value to a byte8 type.</p>
|
||||
*/
|
||||
public static final int I2B = 0x00CA;
|
||||
/**
|
||||
* I2S Opcode: Represents the type conversion operation from int32 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow an int32 value to a short16 type.</p>
|
||||
*/
|
||||
public static final int I2S = 0x00CB;
|
||||
/**
|
||||
* I2L Opcode: Represents the type conversion operation from int32 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is commonly used to widen an int32 value to a long64 type.</p>
|
||||
*/
|
||||
public static final int I2L = 0x00CC;
|
||||
/**
|
||||
* I2F Opcode: Represents the type conversion operation from int32 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert an int32 value to a float32 type.</p>
|
||||
*/
|
||||
public static final int I2F = 0x00CD;
|
||||
/**
|
||||
* I2D Opcode: Represents the type conversion operation from int32 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link I2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top int32 value from the operand stack.</li>
|
||||
* <li>Convert the int32 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen an int32 value to a double64 type.</p>
|
||||
*/
|
||||
public static final int I2D = 0x00CE;
|
||||
// endregion Int32
|
||||
|
||||
// region Long64 (0x00CF-0xD3)
|
||||
/**
|
||||
* L2B Opcode: Represents the type conversion operation from long64 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a long64 value to a byte8 type.</p>
|
||||
*/
|
||||
public static final int L2B = 0x00CF;
|
||||
/**
|
||||
* L2S Opcode: Represents the type conversion operation from long64 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a long64 value to a short16 type.</p>
|
||||
*/
|
||||
public static final int L2S = 0x00D0;
|
||||
/**
|
||||
* L2I Opcode: Represents the type conversion operation from long64 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is typically used to narrow a long64 value to an int32 type .</p>
|
||||
*/
|
||||
public static final int L2I = 0x00D1;
|
||||
/**
|
||||
* L2F Opcode: Represents the type conversion operation from long64 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a long64 value to a float32 type.</p>
|
||||
*/
|
||||
public static final int L2F = 0x00D2;
|
||||
/**
|
||||
* L2D Opcode: Represents the type conversion operation from long64 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link L2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top long64 value from the operand stack.</li>
|
||||
* <li>Convert the long64 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a long64 value to a double64 type.</p>
|
||||
*/
|
||||
public static final int L2D = 0x00D3;
|
||||
// endregion Long64
|
||||
|
||||
// region Float32 (0x00D4-0xD8)
|
||||
/**
|
||||
* F2B Opcode: Represents the type conversion operation from float32 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to a byte8 type.</p>
|
||||
*/
|
||||
public static final int F2B = 0x00D4;
|
||||
/**
|
||||
* F2S Opcode: Represents the type conversion operation from float32 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to a short16 type.</p>
|
||||
*/
|
||||
public static final int F2S = 0x00D5;
|
||||
/**
|
||||
* F2I Opcode: Represents the type conversion operation from float32 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to convert a float32 value to an int32 type.</p>
|
||||
*/
|
||||
public static final int F2I = 0x00D6;
|
||||
/**
|
||||
* F2L Opcode: Represents the type conversion operation from float32 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a long64 value.</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to widen a float32 value to a long64 type.</p>
|
||||
*/
|
||||
public static final int F2L = 0x00D7;
|
||||
/**
|
||||
* F2D Opcode: Represents the type conversion operation from float32 to double64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link F2DCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top float32 value from the operand stack.</li>
|
||||
* <li>Convert the float32 value to a double64 value.</li>
|
||||
* <li>Push the converted double64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to promote a float32 value to a double64 type.</p>
|
||||
*/
|
||||
public static final int F2D = 0x00D8;
|
||||
// endregion Float32
|
||||
|
||||
// region Double64 (0x00D9-0xDD)
|
||||
/**
|
||||
* D2B Opcode: Represents the type conversion operation from double64 to byte8 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2BCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a byte8 value (this may involve truncation).</li>
|
||||
* <li>Push the converted byte8 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a byte8 type.</p>
|
||||
*/
|
||||
public static final int D2B = 0x00D9;
|
||||
/**
|
||||
* D2S Opcode: Represents the type conversion operation from double64 to short16 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2SCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a short16 value (this may involve truncation).</li>
|
||||
* <li>Push the converted short16 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a short16 type.</p>
|
||||
*/
|
||||
public static final int D2S = 0x00DA;
|
||||
/**
|
||||
* D2I Opcode: Represents the type conversion operation from double64 to int32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2ICommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to an int32 value (this may involve truncation).</li>
|
||||
* <li>Push the converted int32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to an int32 type.</p>
|
||||
*/
|
||||
public static final int D2I = 0x00DB;
|
||||
/**
|
||||
* D2L Opcode: Represents the type conversion operation from double64 to long64 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2LCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a long64 value (this may involve truncation).</li>
|
||||
* <li>Push the converted long64 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a long64 type.</p>
|
||||
*/
|
||||
public static final int D2L = 0x00DC;
|
||||
/**
|
||||
* D2F Opcode: Represents the type conversion operation from double64 to float32 in the virtual machine.
|
||||
* <p>This opcode is implemented by the {@link D2FCommand} class, which defines its specific execution logic.</p>
|
||||
*
|
||||
* <p>Execution Steps:</p>
|
||||
* <ol>
|
||||
* <li>Pop the top double64 value from the operand stack.</li>
|
||||
* <li>Convert the double64 value to a float32 value.</li>
|
||||
* <li>Push the converted float32 value back onto the operand stack for subsequent operations.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>This opcode is used to narrow a double64 value to a float32 type.</p>
|
||||
*/
|
||||
public static final int D2F = 0x00DD;
|
||||
// endregion Double64
|
||||
// endregion Conversion
|
||||
|
||||
// region Stack Control (0x0100-0x01FF)
|
||||
/**
|
||||
|
||||
@ -207,26 +207,41 @@ public class CommandFactory {
|
||||
// endregion
|
||||
|
||||
// region Type Conversion (0x00C0-0x00DF)
|
||||
COMMANDS[VMOpCode.I2L] = new I2LCommand();
|
||||
COMMANDS[VMOpCode.I2S] = new I2SCommand();
|
||||
COMMANDS[VMOpCode.B2S] = new B2SCommand();
|
||||
COMMANDS[VMOpCode.B2I] = new B2ICommand();
|
||||
COMMANDS[VMOpCode.B2L] = new B2LCommand();
|
||||
COMMANDS[VMOpCode.B2F] = new B2FCommand();
|
||||
COMMANDS[VMOpCode.B2D] = new B2DCommand();
|
||||
|
||||
COMMANDS[VMOpCode.S2B] = new S2BCommand();
|
||||
COMMANDS[VMOpCode.S2I] = new S2ICommand();
|
||||
COMMANDS[VMOpCode.S2L] = new S2LCommand();
|
||||
COMMANDS[VMOpCode.S2F] = new S2FCommand();
|
||||
COMMANDS[VMOpCode.S2D] = new S2DCommand();
|
||||
|
||||
COMMANDS[VMOpCode.I2B] = new I2BCommand();
|
||||
COMMANDS[VMOpCode.I2D] = new I2DCommand();
|
||||
COMMANDS[VMOpCode.I2S] = new I2SCommand();
|
||||
COMMANDS[VMOpCode.I2L] = new I2LCommand();
|
||||
COMMANDS[VMOpCode.I2F] = new I2FCommand();
|
||||
COMMANDS[VMOpCode.I2D] = new I2DCommand();
|
||||
|
||||
COMMANDS[VMOpCode.L2B] = new L2BCommand();
|
||||
COMMANDS[VMOpCode.L2S] = new L2SCommand();
|
||||
COMMANDS[VMOpCode.L2I] = new L2ICommand();
|
||||
COMMANDS[VMOpCode.L2D] = new L2DCommand();
|
||||
COMMANDS[VMOpCode.L2F] = new L2FCommand();
|
||||
COMMANDS[VMOpCode.L2D] = new L2DCommand();
|
||||
|
||||
COMMANDS[VMOpCode.F2B] = new F2BCommand();
|
||||
COMMANDS[VMOpCode.F2S] = new F2SCommand();
|
||||
COMMANDS[VMOpCode.F2I] = new F2ICommand();
|
||||
COMMANDS[VMOpCode.F2L] = new F2LCommand();
|
||||
COMMANDS[VMOpCode.F2D] = new F2DCommand();
|
||||
|
||||
COMMANDS[VMOpCode.D2B] = new D2BCommand();
|
||||
COMMANDS[VMOpCode.D2S] = new D2SCommand();
|
||||
COMMANDS[VMOpCode.D2I] = new D2ICommand();
|
||||
COMMANDS[VMOpCode.D2L] = new D2LCommand();
|
||||
COMMANDS[VMOpCode.D2F] = new D2FCommand();
|
||||
|
||||
COMMANDS[VMOpCode.S2I] = new S2ICommand();
|
||||
COMMANDS[VMOpCode.B2I] = new B2ICommand();
|
||||
// endregion
|
||||
|
||||
// region Stack Control (0x0100-0x01FF)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user