diff --git a/.run/Demo14.run.xml b/.run/Demo14.run.xml
new file mode 100644
index 0000000..6071504
--- /dev/null
+++ b/.run/Demo14.run.xml
@@ -0,0 +1,10 @@
+
- * 工作流程简述: + * 工作流程简述: *
+ * 本类负责将中间表示(IR)中的函数调用指令 {@link CallInstruction} 转换为虚拟机(VM)指令。 + * 支持普通函数调用和特殊的 syscall 指令转换。 + *
+ * + *+ * 能力说明: + *
用于记录虚拟寄存器与其绑定字符串常量的映射。由 {@link LoadConstGenerator} 在编译期间填充。
+ */ + private static final Map供 {@link LoadConstGenerator} 在加载字符串常量时调用。
+ * + * @param regId 虚拟寄存器 id + * @param value 字符串常量值 + */ + public static void registerStringConst(int regId, String value) { + STRING_CONST_POOL.put(regId, value); + } + + /** + * 返回本生成器支持的 IR 指令类型(CallInstruction) + */ @Override public Class+ * 本类负责将 IR 层的常量加载指令 {@link LoadConstInstruction} 转换为对应的虚拟机指令。 + * 额外支持:如果常量类型为 {@code String},会同步登记到 + * {@link CallGenerator} 的字符串常量池,方便 syscall 降级场景使用。 + *
*/ public class LoadConstGenerator implements InstructionGenerator
- * 该类负责将抽象语法树(AST)的表达式节点转换为中间表示(IR)指令和虚拟寄存器,
- * 是编译器IR生成阶段的核心工具。
- *
- * 主要职责包括:
+ * 负责将 AST 表达式节点递归转换为 IR 虚拟寄存器操作,并生成对应的 IR 指令序列。
+ * 支持字面量、标识符、二元表达式、一元表达式、函数调用等多种类型表达式。
+ *
+ * 主要功能: *
+ *
*/ public record ExpressionBuilder(IRContext ctx) { - /** - * 构建并返回某个表达式节点对应的虚拟寄存器。 - * - *会根据节点的实际类型分别处理: - *
-x(取负,生成 NEG_I32 指令)与x == 0 比较指令)+ * 这是表达式 IR 生成的核心入口。它会根据不同的表达式类型进行分派,递归构建 IR 指令。 + *
+ * + * @param expr 任意 AST 表达式节点 + * @return 存储该表达式结果的虚拟寄存器 + * @throws IllegalStateException 遇到不支持的表达式类型或未定义标识符 + */ public IRVirtualRegister build(ExpressionNode expr) { return switch (expr) { - // 数字字面量 + // 数字字面量,例如 123、3.14 case NumberLiteralNode n -> buildNumberLiteral(n.value()); - // 布尔字面量 + // 字符串字面量,例如 "abc" + case StringLiteralNode s -> buildStringLiteral(s.value()); + // 布尔字面量,例如 true / false case BoolLiteralNode b -> buildBoolLiteral(b.getValue()); - // 标识符 + // 标识符(变量名),如 a、b case IdentifierNode id -> { + // 查找当前作用域中的变量寄存器 IRVirtualRegister reg = ctx.getScope().lookup(id.name()); if (reg == null) throw new IllegalStateException("未定义标识符: " + id.name()); yield reg; } - // 二元表达式 + // 二元表达式(如 a+b, x==y) case BinaryExpressionNode bin -> buildBinary(bin); - // 函数调用 - case CallExpressionNode call -> buildCall(call); - case UnaryExpressionNode u -> buildUnary(u); + // 函数/方法调用表达式 + case CallExpressionNode call -> buildCall(call); + // 一元表达式(如 -a, !a) + case UnaryExpressionNode un -> buildUnary(un); + + // 默认分支:遇到未知表达式类型则直接抛异常 default -> throw new IllegalStateException( "不支持的表达式类型: " + expr.getClass().getSimpleName()); }; } - /** 处理一元表达式 */ - private IRVirtualRegister buildUnary(UnaryExpressionNode un) { - String op = un.operator(); - IRVirtualRegister val = build(un.operand()); - - // -x → NEG_*(根据类型自动选择位宽) - if (op.equals("-")) { - IRVirtualRegister dest = ctx.newRegister(); - IROpCode code = ExpressionUtils.negOp(un.operand()); - ctx.addInstruction(new UnaryOperationInstruction(code, dest, val)); - return dest; - } - - // !x → (x == 0) - if (op.equals("!")) { - IRVirtualRegister zero = InstructionFactory.loadConst(ctx, 0); - return InstructionFactory.binOp(ctx, IROpCode.CMP_IEQ, val, zero); - } - - throw new IllegalStateException("未知一元运算符: " + op); - } + /* ───────────────── 写入指定寄存器 ───────────────── */ /** - * 直接将表达式计算结果写入指定的目标寄存器(dest)。 - *- * 与{@link #build(ExpressionNode)}类似,但支持目标寄存器复用(避免不必要的move)。 + * 生成表达式,并将其结果直接写入目标寄存器,避免冗余的 move 操作。 * - * @param node 表达式AST节点 - * @param dest 目标寄存器 - * @throws IllegalStateException 未定义标识符/不支持的表达式类型时报错 + *
+ * 某些简单表达式(如字面量、变量名)可以直接写入目标寄存器;复杂表达式则会先 build 到新寄存器,再 move 到目标寄存器。 + *
+ * + * @param node 要生成的表达式节点 + * @param dest 目标虚拟寄存器(用于存储结果) */ public void buildInto(ExpressionNode node, IRVirtualRegister dest) { switch (node) { - // 数字字面量,直接加载到目标寄存器 + // 数字字面量:生成 loadConst 指令写入目标寄存器 case NumberLiteralNode n -> - InstructionFactory.loadConstInto(ctx, dest, ExpressionUtils.buildNumberConstant(ctx, n.value())); - // 标识符,查找并move到目标寄存器 + InstructionFactory.loadConstInto( + ctx, dest, ExpressionUtils.buildNumberConstant(ctx, n.value())); + + // 字符串字面量:生成 loadConst 指令写入目标寄存器 + case StringLiteralNode s -> + InstructionFactory.loadConstInto( + ctx, dest, new IRConstant(s.value())); + + // 布尔字面量:转换为 int 1/0,生成 loadConst + case BoolLiteralNode b -> + InstructionFactory.loadConstInto( + ctx, dest, new IRConstant(b.getValue() ? 1 : 0)); + + // 标识符:查表获取原寄存器,然后 move 到目标寄存器 case IdentifierNode id -> { IRVirtualRegister src = ctx.getScope().lookup(id.name()); - if (src == null) throw new IllegalStateException("未定义标识符: " + id.name()); + if (src == null) + throw new IllegalStateException("未定义标识符: " + id.name()); InstructionFactory.move(ctx, src, dest); } - // 二元表达式,直接写入目标寄存器 + + // 二元表达式:递归生成并写入目标寄存器 case BinaryExpressionNode bin -> buildBinaryInto(bin, dest); - // 其他表达式,先递归生成寄存器,再move到目标寄存器 + + // 其它复杂情况:先 build 到新寄存器,再 move 到目标寄存器 default -> { IRVirtualRegister tmp = build(node); InstructionFactory.move(ctx, tmp, dest); @@ -127,41 +123,100 @@ public record ExpressionBuilder(IRContext ctx) { } } + /* ───────────────── 具体表达式类型 ───────────────── */ + /** - * 构建二元表达式的IR,生成新寄存器存储结果。 - *- * 先递归构建左右操作数,之后根据操作符类别(算术或比较)决定生成的IR操作码, - * 并生成对应的二元运算指令。 + * 一元表达式构建 * - * @param bin 二元表达式节点 - * @return 存放结果的虚拟寄存器 + *
+ * 支持算术取负(-a)、逻辑非(!a)等一元运算符。 + *
+ * + * @param un 一元表达式节点 + * @return 结果存储的新分配虚拟寄存器 */ - private IRVirtualRegister buildBinary(BinaryExpressionNode bin) { - String op = bin.operator(); - IRVirtualRegister left = build(bin.left()); - IRVirtualRegister right = build(bin.right()); + private IRVirtualRegister buildUnary(UnaryExpressionNode un) { + // 递归生成操作数的寄存器 + IRVirtualRegister src = build(un.operand()); + // 分配目标寄存器 + IRVirtualRegister dest = ctx.newRegister(); - // 1. 比较运算 - if (ComparisonUtils.isComparisonOperator(op)) { - return InstructionFactory.binOp( - ctx, - ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()), - left, right); + switch (un.operator()) { + // 算术负号:生成取负指令 + case "-" -> ctx.addInstruction( + new UnaryOperationInstruction(ExpressionUtils.negOp(un.operand()), dest, src)); + // 逻辑非:等价于 a == 0,生成比较指令 + case "!" -> { + IRVirtualRegister zero = InstructionFactory.loadConst(ctx, 0); + return InstructionFactory.binOp(ctx, IROpCode.CMP_IEQ, src, zero); + } + // 其它一元运算符不支持,抛异常 + default -> throw new IllegalStateException("未知一元运算符: " + un.operator()); } - - // 2. 其他算术 / 逻辑运算 - IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right()); - if (code == null) throw new IllegalStateException("不支持的运算符: " + op); - return InstructionFactory.binOp(ctx, code, left, right); + return dest; } /** - * 将二元表达式的结果直接写入指定寄存器dest。 - *
- * 结构与{@link #buildBinary(BinaryExpressionNode)}类似,但不会新分配寄存器。
+ * 构建函数或方法调用表达式。
+ *
+ * @param call AST 调用表达式节点
+ * @return 存储调用结果的虚拟寄存器
+ */
+ private IRVirtualRegister buildCall(CallExpressionNode call) {
+ // 递归生成所有参数(实参)对应的寄存器
+ List
- * 支持普通标识符调用和成员调用(如 mod.func),会为每个参数依次生成子表达式的寄存器。
- *
- * @param call 调用表达式AST节点
- * @return 返回结果存放的寄存器
- */
- private IRVirtualRegister buildCall(CallExpressionNode call) {
- // 递归构建所有参数的寄存器
- List
- * 会将字符串型字面量(如 "123", "1.0f")解析为具体的IRConstant,
- * 并分配一个新的虚拟寄存器来存放该常量。
+ * 构建数字字面量表达式(如 123),分配新寄存器并生成 LoadConst 指令。
*
- * @param value 字面量字符串
- * @return 存放该常量的寄存器
+ * @param value 字面量文本(字符串格式)
+ * @return 存储该字面量的寄存器
*/
private IRVirtualRegister buildNumberLiteral(String value) {
- IRConstant constant = ExpressionUtils.buildNumberConstant(ctx, value);
- IRVirtualRegister reg = ctx.newRegister();
- ctx.addInstruction(new LoadConstInstruction(reg, constant));
- return reg;
+ IRConstant c = ExpressionUtils.buildNumberConstant(ctx, value);
+ IRVirtualRegister r = ctx.newRegister();
+ ctx.addInstruction(new LoadConstInstruction(r, c));
+ return r;
}
- /** 布尔字面量 → CONST (true=1,false=0)*/
- private IRVirtualRegister buildBoolLiteral(boolean value) {
- IRConstant constant = new IRConstant(value ? 1 : 0);
- IRVirtualRegister reg = ctx.newRegister();
- ctx.addInstruction(new LoadConstInstruction(reg, constant));
- return reg;
+ /**
+ * 构建字符串字面量表达式,分配新寄存器并生成 LoadConst 指令。
+ *
+ * @param value 字符串内容
+ * @return 存储该字符串的寄存器
+ */
+ private IRVirtualRegister buildStringLiteral(String value) {
+ IRConstant c = new IRConstant(value);
+ IRVirtualRegister r = ctx.newRegister();
+ ctx.addInstruction(new LoadConstInstruction(r, c));
+ return r;
+ }
+
+ /**
+ * 构建布尔字面量表达式(true/false),分配新寄存器并生成 LoadConst 指令(1 表示 true,0 表示 false)。
+ *
+ * @param v 布尔值
+ * @return 存储 1/0 的寄存器
+ */
+ private IRVirtualRegister buildBoolLiteral(boolean v) {
+ IRConstant c = new IRConstant(v ? 1 : 0);
+ IRVirtualRegister r = ctx.newRegister();
+ ctx.addInstruction(new LoadConstInstruction(r, c));
+ return r;
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
index 8c2eddc..df0993c 100644
--- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
@@ -20,7 +20,7 @@ import java.util.List;
*
* 它负责处理类似 {@code callee(arg1, arg2, ...)} 形式的调用表达式,执行如下操作:
*
- * 本类主要负责:
+ * 该类统一注册编译器需要用到的所有基础类型、标准库模块与内核函数,供语义分析及类型检查阶段使用。
*
- * 用于类型解析过程(如解析变量声明或函数返回类型)中,
- * 将用户源码中的类型字符串转换为语义类型对象。
+ * 本 Map 静态初始化,注册所有 Snow 语言基础类型,供类型检查与类型推断使用。
+ *
- * 当前实现将内置模块 {@code BuiltinUtils} 注册至上下文模块表中,
- * 使其在用户代码中可被访问(如 {@code BuiltinUtils.to_string(...)})。
+ * 初始化内置模块和函数声明
*
- * @param ctx 当前语义分析上下文
+ *
+ * 语义分析阶段调用,将所有基础模块与函数声明注册到语义上下文中。
+ * - 目前注册 BuiltinUtils 标准库模块(仅注册签名,不负责具体实现)。
+ * - syscall 函数注册到 BuiltinUtils 内,供标准库内部调用。
+ *
+ * This command facilitates method invocation by creating a new stack frame, transferring arguments
+ * from the operand stack to the callee's local variable store, and jumping to the specified target address.
+ * Specific behavior:
+ * This method handles the creation of a new stack frame for the callee, argument passing,
+ * and control transfer to the target function address.
+ *
+ * This instruction loads a reference object from the current stack frame’s local variable store
+ * at the specified slot and pushes it onto the operand stack.
+ * Instruction format: {@code R_LOAD Behavior:
+ * This instruction pushes a reference object, such as a String literal, onto the operand stack.
+ * Instruction format: {@code R_PUSH Behavior:
+ * This instruction pops a reference object from the top of the operand stack
+ * and stores it in the local variable table at the specified slot index of the current stack frame.
+ * Instruction format: {@code R_STORE Behavior:
+ * 本类负责将虚拟机指令集中的 SYSCALL 进行分派,模拟现实系统常见的文件、网络、管道、标准输出等操作,
+ * 通过操作数栈完成参数、返回值传递,并借助文件描述符表(FDTable)进行底层资源管理。
+ * 所有 I/O 相关功能均基于 Java NIO 实现,兼容多种 I/O 场景。
+ * 参数与栈约定: 异常与失败处理: 支持的子命令示例:
+ * 本方法负责将底层虚拟机传递的 flags 整数型位域,转换为 Java NIO 标准的文件打开选项集合,
+ * 以支持文件读、写、创建、截断、追加等多种访问场景。
+ * 常用于 SYSCALL 的 OPEN 子命令。
+ *
+ * 本方法是全局错误屏障,任何命令异常都会转换为虚拟机通用的失败信号,
+ * 保证上层调用逻辑不会被异常打断。实际应用中可拓展错误码机制。
+ *
+ * 该方法用于 SYSCALL PRINT/PRINTLN,将任意类型对象转为易读字符串输出到标准输出流。
+ * 字节数组自动按 UTF-8 解码,其它原生数组按格式化字符串输出。
+ *
+ * 本方法针对 int、long、double、float、short、char、byte、boolean 等所有原生数组类型
+ * 以及对象数组都能正确格式化,统一输出格式风格,避免显示为类型 hashCode。
+ * 若为不支持的类型,返回通用提示字符串。
+ * This opcode is implemented by the {@link RPushCommand} class, which defines its specific execution logic. Execution Steps: This opcode is commonly used for: This opcode is implemented by the {@link RLoadCommand} class, which defines its specific execution logic. Execution Steps: This opcode is commonly used for: This opcode is implemented by the {@link RStoreCommand} class, which defines its specific execution logic. Execution Steps: This opcode is commonly used for: This opcode is implemented by the {@link SyscallCommand} class, which defines its specific execution logic. Execution Steps:
+ * 支持算术、位运算与比较(==, !=, >, <, ...)。
*
* @param bin 二元表达式节点
- * @param dest 目标寄存器
+ * @return 存储表达式结果的虚拟寄存器
+ */
+ private IRVirtualRegister buildBinary(BinaryExpressionNode bin) {
+ // 递归生成左、右子表达式的寄存器
+ IRVirtualRegister a = build(bin.left());
+ IRVirtualRegister b = build(bin.right());
+ String op = bin.operator();
+
+ // 比较运算符(==、!=、>、< 等),需要生成条件跳转或布尔值寄存器
+ if (ComparisonUtils.isComparisonOperator(op)) {
+ return InstructionFactory.binOp(
+ ctx,
+ // 通过比较工具获得合适的 IR 操作码
+ ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()),
+ a, b);
+ }
+
+ // 其它算术/位运算
+ IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right());
+ if (code == null) throw new IllegalStateException("不支持的运算符: " + op);
+ return InstructionFactory.binOp(ctx, code, a, b);
+ }
+
+ /**
+ * 二元表达式构建,结果直接写入目标寄存器(用于赋值左值等优化场景)。
+ *
+ * @param bin 二元表达式节点
+ * @param dest 目标虚拟寄存器
*/
private void buildBinaryInto(BinaryExpressionNode bin, IRVirtualRegister dest) {
IRVirtualRegister a = build(bin.left());
@@ -180,54 +235,44 @@ public record ExpressionBuilder(IRContext ctx) {
}
}
- /**
- * 处理函数调用表达式,生成对应的Call指令和目标寄存器。
- *
- *
- *
- * 该类为纯工具类,所有成员均为静态,不可实例化。
+ *
+ *
*/
public class CallCommand implements Command {
+ /**
+ * Executes the CALL instruction, initiating a subroutine/function call within the virtual machine.
+ *
+ *
+ * @param currentPC The current program counter, used to record the return address for after the call.
+ * @param operandStack The operand stack manager. Arguments are popped from this stack.
+ * @param callerLVS The local variable store of the caller function (not directly modified here).
+ * @param callStack The virtual machine's call stack manager, used to push the new stack frame.
+ * @return The new program counter value, which is the address of the callee function (i.e., jump target).
+ * The VM should transfer control to this address after setting up the call frame.
+ * @throws IllegalArgumentException If the instruction parameters are malformed or missing.
+ * @throws IllegalStateException If the operand stack does not contain enough arguments.
+ */
@Override
public int execute(String[] parts,
int currentPC,
@@ -44,7 +80,7 @@ public class CallCommand implements Command {
new MethodContext("subroutine@" + targetAddr, null));
callStack.pushFrame(newFrame);
- System.out.println("Calling function at address: " + targetAddr);
+ System.out.println("\nCalling function at address: " + targetAddr);
return targetAddr; // jump
}
}
diff --git a/src/main/java/org/jcnc/snow/vm/commands/flow/control/RetCommand.java b/src/main/java/org/jcnc/snow/vm/commands/flow/control/RetCommand.java
index 1e4ebd5..505f378 100644
--- a/src/main/java/org/jcnc/snow/vm/commands/flow/control/RetCommand.java
+++ b/src/main/java/org/jcnc/snow/vm/commands/flow/control/RetCommand.java
@@ -44,7 +44,7 @@ public class RetCommand implements Command {
finished.getLocalVariableStore().clearVariables();
int returnAddr = finished.getReturnAddress();
- System.out.println("Return " + returnAddr);
+ System.out.println("\nReturn " + returnAddr);
return returnAddr;
}
}
diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java
new file mode 100644
index 0000000..d7e314d
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java
@@ -0,0 +1,54 @@
+package org.jcnc.snow.vm.commands.ref.control;
+
+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;
+
+/**
+ * The {@code RLoadCommand} class implements the {@link Command} interface and represents the
+ * reference load instruction ({@code R_LOAD}) in the virtual machine.
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+public final class RLoadCommand implements Command {
+
+ /**
+ * Executes the {@code R_LOAD} instruction, loading a reference from the local variable table and pushing it onto the operand stack.
+ *
+ * @param parts The instruction parameters. {@code parts[0]} is the operator ("R_LOAD"), {@code parts[1]} is the slot index.
+ * @param pc The current program counter value, indicating the instruction address being executed.
+ * @param stack The operand stack manager. The loaded reference will be pushed onto this stack.
+ * @param lvs The local variable store. (Not used directly, as this command uses the store from the current stack frame.)
+ * @param cs The call stack manager. The reference will be loaded from the local variable store of the top stack frame.
+ * @return The next program counter value ({@code pc + 1}), pointing to the next instruction.
+ * @throws NumberFormatException if the slot parameter cannot be parsed as an integer.
+ */
+ @Override
+ public int execute(String[] parts, int pc,
+ OperandStack stack,
+ LocalVariableStore lvs,
+ CallStack cs) {
+
+ int slot = Integer.parseInt(parts[1]);
+ Object v = cs.peekFrame().getLocalVariableStore().getVariable(slot);
+ stack.push(v);
+ return pc + 1;
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java
new file mode 100644
index 0000000..1386018
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java
@@ -0,0 +1,63 @@
+package org.jcnc.snow.vm.commands.ref.control;
+
+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;
+
+/**
+ * The {@code RPushCommand} class implements the {@link Command} interface and represents the
+ * reference push instruction ({@code R_PUSH}) in the virtual machine.
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+public final class RPushCommand implements Command {
+
+ /**
+ * Executes the {@code R_PUSH} instruction, pushing a reference (such as a string literal)
+ * onto the operand stack.
+ *
+ * @param parts The instruction parameters. {@code parts[0]} is the operator ("R_PUSH"),
+ * {@code parts[1..]} are the parts of the literal to be concatenated and pushed.
+ * @param pc The current program counter value, indicating the instruction address being executed.
+ * @param stack The operand stack manager. The literal will be pushed onto this stack.
+ * @param lvs The local variable store. (Not used in this instruction.)
+ * @param cs The call stack manager. (Not used in this instruction.)
+ * @return The next program counter value ({@code pc + 1}), pointing to the next instruction.
+ * @throws IllegalStateException if the instruction is missing required parameters.
+ */
+ @Override
+ public int execute(String[] parts, int pc,
+ OperandStack stack,
+ LocalVariableStore lvs,
+ CallStack cs) {
+
+ if (parts.length < 2)
+ throw new IllegalStateException("R_PUSH missing parameter");
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i < parts.length; i++) {
+ if (i > 1) sb.append(' ');
+ sb.append(parts[i]);
+ }
+ stack.push(sb.toString());
+ return pc + 1;
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java
new file mode 100644
index 0000000..0237908
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java
@@ -0,0 +1,58 @@
+package org.jcnc.snow.vm.commands.ref.control;
+
+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;
+
+/**
+ * The {@code RStoreCommand} class implements the {@link Command} interface and represents the
+ * reference store instruction ({@code R_STORE}) in the virtual machine.
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+public final class RStoreCommand implements Command {
+
+ /**
+ * Executes the {@code R_STORE} instruction, storing a reference object from the top of the operand stack
+ * into the local variable table of the current stack frame.
+ *
+ * @param parts The instruction parameters. {@code parts[0]} is the operator ("R_STORE"),
+ * {@code parts[1]} is the slot index.
+ * @param pc The current program counter value, indicating the instruction address being executed.
+ * @param stack The operand stack manager. The reference object will be popped from this stack.
+ * @param lvs The local variable store. (Not used directly, as the store from the current stack frame is used.)
+ * @param cs The call stack manager. The reference will be stored in the local variable store of the top stack frame.
+ * @return The next program counter value ({@code pc + 1}), pointing to the next instruction.
+ * @throws NumberFormatException if the slot parameter cannot be parsed as an integer.
+ * @throws java.util.EmptyStackException if the operand stack is empty when popping.
+ */
+ @Override
+ public int execute(String[] parts, int pc,
+ OperandStack stack,
+ LocalVariableStore lvs,
+ CallStack cs) {
+
+ int slot = Integer.parseInt(parts[1]);
+ Object v = stack.pop();
+ cs.peekFrame().getLocalVariableStore().setVariable(slot, v);
+ return pc + 1;
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java b/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java
index 06a5da4..71e208c 100644
--- a/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java
+++ b/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java
@@ -59,7 +59,7 @@ public class HaltCommand implements Command {
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Output the termination message
- LoggingUtils.logInfo("Process has ended", "\n");
+ LoggingUtils.logInfo("\nProcess has ended", "");
// Return -1 to indicate the program termination, and the virtual machine will not continue executing subsequent instructions
return -1;
diff --git a/src/main/java/org/jcnc/snow/vm/commands/system/control/SyscallCommand.java b/src/main/java/org/jcnc/snow/vm/commands/system/control/SyscallCommand.java
new file mode 100644
index 0000000..90caf8b
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/vm/commands/system/control/SyscallCommand.java
@@ -0,0 +1,340 @@
+package org.jcnc.snow.vm.commands.system.control;
+
+import org.jcnc.snow.vm.interfaces.Command;
+import org.jcnc.snow.vm.io.FDTable;
+import org.jcnc.snow.vm.module.CallStack;
+import org.jcnc.snow.vm.module.LocalVariableStore;
+import org.jcnc.snow.vm.module.OperandStack;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.nio.file.OpenOption;
+import java.nio.file.Paths;
+import java.util.*;
+
+import static java.nio.file.StandardOpenOption.*;
+
+/**
+ * SyscallCommand —— 虚拟机系统调用(SYSCALL)指令实现。
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+public class SyscallCommand implements Command {
+
+ /**
+ * 分发并执行 SYSCALL 子命令,根据子命令类型从操作数栈取出参数、操作底层资源,并将结果压回栈顶。
+ *
+ * @param parts 指令及子命令参数分割数组,parts[1]为子命令名
+ * @param pc 当前指令计数器
+ * @param stack 操作数栈
+ * @param locals 局部变量表
+ * @param callStack 调用栈
+ * @return 下一条指令的 pc 值(通常为 pc+1)
+ * @throws IllegalArgumentException 缺少子命令参数时抛出
+ * @throws UnsupportedOperationException 不支持的 SYSCALL 子命令时抛出
+ */
+ @Override
+ public int execute(String[] parts, int pc,
+ OperandStack stack,
+ LocalVariableStore locals,
+ CallStack callStack) {
+
+ if (parts.length < 2) {
+ throw new IllegalArgumentException("SYSCALL missing subcommand");
+ }
+
+ String cmd = parts[1].toUpperCase(Locale.ROOT);
+
+ try {
+ switch (cmd) {
+ // 文件相关操作
+ case "OPEN" -> {
+ int mode = (Integer) stack.pop();
+ int flags = (Integer) stack.pop();
+ String path = String.valueOf(stack.pop());
+ FileChannel fc = FileChannel.open(Paths.get(path), flagsToOptions(flags));
+ stack.push(FDTable.register(fc));
+ }
+ case "CLOSE" -> {
+ int fd = (Integer) stack.pop();
+ FDTable.close(fd);
+ stack.push(0);
+ }
+ case "READ" -> {
+ int count = (Integer) stack.pop();
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (!(ch instanceof ReadableByteChannel rch)) {
+ stack.push(new byte[0]);
+ break;
+ }
+ ByteBuffer buf = ByteBuffer.allocate(count);
+ int n = rch.read(buf);
+ if (n < 0) n = 0;
+ buf.flip();
+ byte[] out = new byte[n];
+ buf.get(out);
+ stack.push(out);
+ }
+ case "WRITE" -> {
+ Object dataObj = stack.pop();
+ int fd = (Integer) stack.pop();
+ byte[] data = (dataObj instanceof byte[] b)
+ ? b
+ : String.valueOf(dataObj).getBytes();
+ Channel ch = FDTable.get(fd);
+ if (!(ch instanceof WritableByteChannel wch)) {
+ stack.push(-1);
+ break;
+ }
+ int written = wch.write(ByteBuffer.wrap(data));
+ stack.push(written);
+ }
+ case "SEEK" -> {
+ int whence = (Integer) stack.pop();
+ long off = ((Number) stack.pop()).longValue();
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (!(ch instanceof SeekableByteChannel sbc)) {
+ stack.push(-1);
+ break;
+ }
+ SeekableByteChannel newPos = switch (whence) {
+ case 0 -> sbc.position(off);
+ case 1 -> sbc.position(sbc.position() + off);
+ case 2 -> sbc.position(sbc.size() + off);
+ default -> throw new IllegalArgumentException("Invalid offset type");
+ };
+ stack.push(newPos);
+ }
+
+ // 管道与描述符操作
+ case "PIPE" -> {
+ Pipe p = Pipe.open();
+ stack.push(FDTable.register(p.sink()));
+ stack.push(FDTable.register(p.source()));
+ }
+ case "DUP" -> {
+ int oldfd = (Integer) stack.pop();
+ stack.push(FDTable.dup(oldfd));
+ }
+
+ // 网络相关
+ case "SOCKET" -> {
+ int proto = (Integer) stack.pop();
+ int type = (Integer) stack.pop();
+ int domain = (Integer) stack.pop();
+ Channel ch = (type == 1)
+ ? SocketChannel.open()
+ : DatagramChannel.open();
+ stack.push(FDTable.register(ch));
+ }
+ case "CONNECT" -> {
+ int port = (Integer) stack.pop();
+ String host = String.valueOf(stack.pop());
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (ch instanceof SocketChannel sc) {
+ sc.connect(new InetSocketAddress(host, port));
+ stack.push(0);
+ } else {
+ stack.push(-1);
+ }
+ }
+ case "BIND" -> {
+ int port = (Integer) stack.pop();
+ String host = String.valueOf(stack.pop());
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (ch instanceof ServerSocketChannel ssc) {
+ ssc.bind(new InetSocketAddress(host, port));
+ stack.push(0);
+ } else {
+ stack.push(-1);
+ }
+ }
+ case "LISTEN" -> {
+ int backlog = (Integer) stack.pop();
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (ch instanceof ServerSocketChannel) {
+ stack.push(0);
+ } else {
+ stack.push(-1);
+ }
+ }
+ case "ACCEPT" -> {
+ int fd = (Integer) stack.pop();
+ Channel ch = FDTable.get(fd);
+ if (ch instanceof ServerSocketChannel ssc) {
+ SocketChannel cli = ssc.accept();
+ stack.push(FDTable.register(cli));
+ } else {
+ stack.push(-1);
+ }
+ }
+
+ // 多路复用
+ case "SELECT" -> {
+ long timeout = ((Number) stack.pop()).longValue();
+ @SuppressWarnings("unchecked")
+ List
+ *
+ *
+ *
+ *
+ */
+ public static final int R_PUSH = 0x00E0;
+ /**
+ * R_LOAD Opcode: Represents an operation that loads an object reference from the local variable table
+ * and pushes it onto the operand stack.
+ *
+ *
+ *
+ *
+ *
+ */
+ public static final int R_LOAD = 0x00E1;
+ /**
+ * R_STORE Opcode: Represents an operation that pops an object reference from the top of the operand stack
+ * and stores it into the local variable table at the specified slot index.
+ *
+ *
+ *
+ *
+ *
+ */
+ public static final int R_STORE = 0x00E2;
+ // endregion
+
// region Stack Control (0x0100-0x01FF)
/**
* POP Opcode: Represents a stack operation that removes the top element from the operand stack.
@@ -2646,8 +2718,18 @@ public class VMOpCode {
*
*/
public static final int HALT = 0x0400;
+ /**
+ * SYSCALL Opcode: Represents a system call operation that invokes a system-level function or service.
+ *
+ *
+ * 0 → stdin (ReadableByteChannel)
+ * 1 → stdout (WritableByteChannel)
+ * 2 → stderr (WritableByteChannel)
+ * 3+ → 运行期动态分配
+ *
+ */
+public final class FDTable {
+
+ private FDTable() {}
+
+ /** 下一次可用 fd(0‒2 保留给标准流) */
+ private static final AtomicInteger NEXT_FD = new AtomicInteger(3);
+ /** 主映射表:fd → Channel */
+ private static final ConcurrentHashMap