From 7bd795b796e52edec9bfc82b92784b9a847006bf Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Mon, 16 Jun 2025 22:37:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=2064=20=E4=BD=8D?= =?UTF-8?q?=E6=95=B4=E6=95=B0=E6=AF=94=E8=BE=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/generator/CmpJumpGenerator.java | 4 +- .../compiler/backend/util/IROpCodeMapper.java | 9 ++ .../snow/compiler/backend/util/OpHelper.java | 6 + .../jcnc/snow/compiler/ir/core/IROpCode.java | 22 ++- .../compiler/ir/core/IROpCodeMappings.java | 12 +- .../snow/compiler/ir/utils/IROpCodeUtils.java | 12 +- .../commands/control/long64/LCECommand.java | 76 +++++++++++ .../commands/control/long64/LCGCommand.java | 76 +++++++++++ .../commands/control/long64/LCGECommand.java | 76 +++++++++++ .../commands/control/long64/LCLCommand.java | 76 +++++++++++ .../commands/control/long64/LCLECommand.java | 76 +++++++++++ .../commands/control/long64/LCNECommand.java | 76 +++++++++++ .../org/jcnc/snow/vm/engine/VMOpCode.java | 129 ++++++++++++++++++ .../snow/vm/factories/CommandFactory.java | 10 ++ 14 files changed, 639 insertions(+), 21 deletions(-) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCECommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGECommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLECommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/control/long64/LCNECommand.java diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java index 5f15051..b660c11 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java @@ -46,9 +46,9 @@ public class CmpJumpGenerator implements InstructionGenerator b - CMP_LE, // 小于等于:a <= b - CMP_GE, // 大于等于:a >= b + /* ───── 逻辑与比较运算指令(32位整数:int) ───── */ + CMP_EQ, // 32位相等比较:a == b + CMP_NE, // 32位不等比较:a != b + CMP_LT, // 32位小于比较:a < b + CMP_GT, // 32位大于比较:a > b + CMP_LE, // 32位小于等于:a <= b + CMP_GE, // 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 /* ───── 数据访问与常量操作 ───── */ LOAD, // 从内存加载数据至寄存器 diff --git a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java index 69e985e..78f38f0 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCodeMappings.java @@ -40,11 +40,11 @@ public final class IROpCodeMappings { ); // 比较操作符映射 public static final Map CMP = Map.of( - "==", IROpCode.CMP_EQ, - "!=", IROpCode.CMP_NE, - "<", IROpCode.CMP_LT, - ">", IROpCode.CMP_GT, - "<=", IROpCode.CMP_LE, - ">=", IROpCode.CMP_GE + "==", IROpCode.CMP_LEQ, + "!=", IROpCode.CMP_LNE, + "<", IROpCode.CMP_LLT, + ">", IROpCode.CMP_LGT, + "<=", IROpCode.CMP_LLE, + ">=", IROpCode.CMP_LGE ); } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java index dee9733..fb2eba0 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/IROpCodeUtils.java @@ -9,12 +9,12 @@ import java.util.Map; */ public class IROpCodeUtils { private static final Map INVERT = Map.of( - IROpCode.CMP_EQ, IROpCode.CMP_NE, - IROpCode.CMP_NE, IROpCode.CMP_EQ, - IROpCode.CMP_LT, IROpCode.CMP_GE, - IROpCode.CMP_GE, IROpCode.CMP_LT, - IROpCode.CMP_GT, IROpCode.CMP_LE, - IROpCode.CMP_LE, IROpCode.CMP_GT + IROpCode.CMP_LEQ, IROpCode.CMP_LNE, + IROpCode.CMP_LNE, IROpCode.CMP_LEQ, + IROpCode.CMP_LLT, IROpCode.CMP_LGE, + IROpCode.CMP_LGE, IROpCode.CMP_LLT, + IROpCode.CMP_LGT, IROpCode.CMP_LLE, + IROpCode.CMP_LLE, IROpCode.CMP_LGT ); /** diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCECommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCECommand.java new file mode 100644 index 0000000..33ecbfc --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCECommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. + * This class compares two values from the stack, and if they are equal, it jumps to the specified target command. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the two integers are equal, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCECommand implements Command { + /** + * Default constructor for creating an instance of LCECommand. + * This constructor is empty as no specific initialization is required. + */ + public LCECommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the operands are equal, jump to the target command + if (a == b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGCommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGCommand.java new file mode 100644 index 0000000..c9abdee --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGCommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCGCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. + * This class compares two values from the stack, and if the first value is greater than the second, it jumps to the specified target command. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the first integer is greater than the second, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCGCommand implements Command { + /** + * Default constructor for creating an instance of LCGCommand. + * This constructor is empty as no specific initialization is required. + */ + public LCGCommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the first operand is greater than the second, jump to the target command + if (a > b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGECommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGECommand.java new file mode 100644 index 0000000..89f50d3 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCGECommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCGECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. + * This class compares two values from the stack, and if the first value is greater than or equal to the second, it jumps to the specified target command. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the first integer is greater than or equal to the second, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCGECommand implements Command { + /** + * Default constructor for creating an instance of LCGECommand. + * This constructor is empty as no specific initialization is required. + */ + public LCGECommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the first operand is greater than or equal to the second, jump to the target command + if (a >= b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLCommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLCommand.java new file mode 100644 index 0000000..1467371 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLCommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCLCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. + * This class compares two values from the stack, and if the first value is less than the second, it jumps to the specified target command. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the first integer is less than the second, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCLCommand implements Command { + /** + * Default constructor for creating an instance of LCLCommand. + * This constructor is empty as no specific initialization is required. + */ + public LCLCommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the first operand is less than the second, jump to the target command + if (a < b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLECommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLECommand.java new file mode 100644 index 0000000..634b183 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCLECommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCLECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. + * This class compares two values from the stack, and if the first value is less than or equal to the second, it jumps to the specified target command. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the first integer is less than or equal to the second, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCLECommand implements Command { + /** + * Default constructor for creating an instance of LCLECommand. + * This constructor is empty as no specific initialization is required. + */ + public LCLECommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the first operand is less than or equal to the second, jump to the target command + if (a <= b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCNECommand.java b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCNECommand.java new file mode 100644 index 0000000..7aba528 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/control/long64/LCNECommand.java @@ -0,0 +1,76 @@ +package org.jcnc.snow.vm.commands.control.long64; + +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; +import org.jcnc.snow.vm.utils.LoggingUtils; + +/** + * The LCNECommand class implements the {@link Command} interface and represents a conditional jump command + * in the virtual machine that triggers if two values are not equal. + * + *

Specific behavior:

+ *
    + *
  • Pops two integers from the virtual machine stack.
  • + *
  • If the two integers are not equal, jumps to the target command.
  • + *
  • Otherwise, the program continues with the next command.
  • + *
+ */ +public class LCNECommand implements Command { + /** + * Default constructor for creating an instance of LCNECommand. + * This constructor is empty as no specific initialization is required. + */ + public LCNECommand() { + // Empty constructor + } + + /** + * Executes the virtual machine instruction's operation. + * + *

This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's + * specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction + * to be executed.

+ * + *

The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow + * of execution by updating the program counter.

+ * + *

The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching, + * function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame, + * while a `POP` instruction will remove an item from the operand stack.

+ * + * @param parts The array of instruction parameters, which usually includes the operator and related arguments + * (such as target addresses, values, or function names). These parameters may vary based on + * the instruction being executed. + * @param currentPC The current program counter-value, indicating the address of the instruction being executed. + * This value is typically incremented after the execution of each instruction to point to the next one. + * @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack, + * such as pushing, popping, and peeking values. + * @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution. + * The store may not be used in every command but can be leveraged by instructions that require access + * to local variables. + * @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by + * instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions). + * @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the + * instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address + * corresponding to the target of the jump or the subroutine to call. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { + // Parse the target command address + int target = Integer.parseInt(parts[1]); + + // Pop the two operands from the stack + long b = (long) operandStack.pop(); + long a = (long) operandStack.pop(); + + // If the operands are not equal, jump to the target command + if (a != b) { + LoggingUtils.logInfo("Jumping to command", String.valueOf(target)); + return target; + } + + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java index b3a6680..1b2f458 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java @@ -1101,6 +1101,7 @@ public class VMOpCode { // 3. Control Flow Operations (91–110) + // 3.1 JUMP (91-91) /** * JUMP Opcode: Represents an unconditional jump to a target instruction address. *

This opcode is implemented by the {@link JumpCommand} class, which defines its specific execution logic.

@@ -1120,6 +1121,7 @@ public class VMOpCode { * */ public static final int JUMP = 91; + // 3.2 int32 (92-97) /** * IC_E Opcode: Represents a conditional jump based on int32 equality. *

This opcode is implemented by the {@link ICECommand} class, which defines its specific execution logic.

@@ -1246,6 +1248,133 @@ public class VMOpCode { * */ public static final int IC_LE = 97; + // 3.3 long64 (98-103) + /** + * LC_E Opcode: Represents a conditional jump based on long64 equality. + *

This opcode is implemented by the {@link ICECommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the two long64s for equality.
  6. + *
  7. If the long64s are equal, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the long64s are not equal, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as if-statements and loops.
  • + *
+ */ + public static final int LC_E = 98; + /** + * LC_NE Opcode: Represents a conditional jump based on long64 inequality. + *

This opcode is implemented by the {@link ICNECommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the two long64s for inequality.
  6. + *
  7. If the long64s are not equal, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the long64s are equal, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as conditional loops and if-else statements.
  • + *
+ */ + public static final int LC_NE = 99; + /** + * LC_G Opcode: Represents a conditional jump based on long64 comparison (greater than). + *

This opcode is implemented by the {@link ICGCommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the first long64 with the second to determine if it is greater.
  6. + *
  7. If the first long64 is greater than the second, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the first long64 is not greater than the second, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as greater-than conditions in loops and conditional statements.
  • + *
+ */ + public static final int LC_G = 100; + /** + * LC_GE Opcode: Represents a conditional jump based on long64 comparison (greater than or equal to). + *

This opcode is implemented by the {@link ICGECommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the first long64 with the second to determine if it is greater than or equal to the second long64.
  6. + *
  7. If the first long64 is greater than or equal to the second, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the first long64 is less than the second, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as loops, conditional statements, and range checks.
  • + *
+ */ + public static final int LC_GE = 101; + /** + * LC_L Opcode: Represents a conditional jump based on long64 comparison (less than). + *

This opcode is implemented by the {@link ICLCommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the first long64 with the second to determine if it is less than the second long64.
  6. + *
  7. If the first long64 is less than the second, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the first long64 is greater than or equal to the second, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as loops, conditional statements, and range validations.
  • + *
+ */ + public static final int LC_L = 102; + /** + * LC_LE Opcode: Represents a conditional jump based on long64 comparison (less than or equal). + *

This opcode is implemented by the {@link ICLECommand} class, which defines its specific execution logic.

+ * + *

Execution Steps:

+ *
    + *
  1. Parses the target instruction address from the instruction parameters.
  2. + *
  3. Pops two long64 values from the operand stack.
  4. + *
  5. Compares the first long64 with the second to determine if it is less than or equal to the second long64.
  6. + *
  7. If the first long64 is less than or equal to the second, updates the program counter (PC) to the specified target address, + * effectively jumping to the target instruction.
  8. + *
  9. If the first long64 is greater than the second, increments the program counter to proceed with the next sequential instruction.
  10. + *
+ * + *

This opcode is commonly used for:

+ *
    + *
  • Conditional branching in virtual machine execution based on long64 comparison.
  • + *
  • Implementing control flow structures such as loops, conditional statements, and boundary checks.
  • + *
+ */ + public static final int LC_LE = 103; // 4. Stack Operations (111–150) // 4.1 PUSH (111-120) diff --git a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java index 5c8c61b..5ededd8 100644 --- a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java +++ b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java @@ -16,6 +16,7 @@ import org.jcnc.snow.vm.commands.bitwise.long64.LOrCommand; import org.jcnc.snow.vm.commands.bitwise.long64.LXorCommand; import org.jcnc.snow.vm.commands.control.all.JumpCommand; import org.jcnc.snow.vm.commands.control.int32.*; +import org.jcnc.snow.vm.commands.control.long64.*; import org.jcnc.snow.vm.commands.function.CallCommand; import org.jcnc.snow.vm.commands.function.RetCommand; import org.jcnc.snow.vm.commands.memory.all.MovCommand; @@ -142,13 +143,22 @@ public class CommandFactory { COMMANDS[VMOpCode.L_XOR] = new LXorCommand(); // 88 // 3. Control Flow Operations (91–110) + // 3.1 JUMP (91-91) COMMANDS[VMOpCode.JUMP] = new JumpCommand(); // 91 + // 3.2 int32 (92-97) COMMANDS[VMOpCode.IC_E] = new ICECommand(); // 92 COMMANDS[VMOpCode.IC_NE] = new ICNECommand(); // 93 COMMANDS[VMOpCode.IC_G] = new ICGCommand(); // 94 COMMANDS[VMOpCode.IC_GE] = new ICGECommand(); // 95 COMMANDS[VMOpCode.IC_L] = new ICLCommand(); // 96 COMMANDS[VMOpCode.IC_LE] = new ICLECommand(); // 97 + // 3.3 long64 (98-103) + COMMANDS[VMOpCode.LC_E] = new LCECommand(); // 98 + COMMANDS[VMOpCode.LC_NE] = new LCNECommand(); // 99 + COMMANDS[VMOpCode.LC_G] = new LCGCommand(); // 100 + COMMANDS[VMOpCode.LC_GE] = new LCGECommand(); // 101 + COMMANDS[VMOpCode.LC_L] = new LCLCommand(); // 102 + COMMANDS[VMOpCode.LC_LE] = new LCLECommand(); // 103 // 4. Stack Operations (111–150) // 4.1 PUSH (111-120)