errors() {
return errors;
}
@@ -92,7 +112,11 @@ public class Context {
return registry;
}
- /** @return 注册表(快捷方式) */
+ /**
+ * 注册表 getter(快捷方式)。
+ *
+ * @return {@link AnalyzerRegistry} 实例
+ */
public AnalyzerRegistry registry() {
return registry;
}
@@ -113,15 +137,26 @@ public class Context {
// ------------------ 工具函数 ------------------
/**
- * 将类型名称字符串解析为对应的内置 {@link Type} 实例。
+ * 将类型名称字符串解析为对应的类型实例(支持多维数组后缀)。
*
- * 若类型在 {@link BuiltinTypeRegistry#BUILTIN_TYPES} 中存在,则返回对应类型;
- * 否则返回 {@code null},调用方可据此决定是否降级处理。
+ * 例如,"int" → int 类型,"int[][]" → 二维整型数组类型。
+ *
*
- * @param name 类型名称(如 "int", "float", "void", "string" 等)
- * @return 匹配的 {@link Type},若无匹配项则返回 {@code null}
+ * @param name 类型名称(支持 "[]" 数组后缀)
+ * @return 对应的 {@link Type} 实例,若无法识别返回 null
*/
public Type parseType(String name) {
- return BuiltinTypeRegistry.BUILTIN_TYPES.get(name);
+ int dims = 0;
+ while (name.endsWith("[]")) {
+ name = name.substring(0, name.length() - 2);
+ dims++;
+ }
+ Type base = BuiltinTypeRegistry.BUILTIN_TYPES.get(name);
+ if (base == null) return null;
+ Type t = base;
+ for (int i = 0; i < dims; i++) {
+ t = new ArrayType(t);
+ }
+ return t;
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/ArrayType.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/ArrayType.java
new file mode 100644
index 0000000..9b7bd41
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/ArrayType.java
@@ -0,0 +1,73 @@
+package org.jcnc.snow.compiler.semantic.type;
+
+import java.util.Objects;
+
+/**
+ * {@code ArrayType} 表示数组类型,每个数组类型包含其元素类型。
+ *
+ * 例如,int[]、string[] 等均可用本类表示。内部通过 {@link #elementType()} 字段保存元素类型。
+ *
+ */
+public record ArrayType(
+ /*
+ 数组元素的类型。
+ */
+ Type elementType
+) implements Type {
+
+ /**
+ * 判断当前数组类型能否与另一类型兼容(主要用于类型检查)。
+ *
+ * 只有当 {@code other} 也是 ArrayType,且元素类型兼容时返回 true。
+ *
+ *
+ * @param other 需判断的类型
+ * @return 类型兼容性结果
+ */
+ @Override
+ public boolean isCompatible(Type other) {
+ if (!(other instanceof ArrayType(Type type))) return false;
+ return elementType.isCompatible(type);
+ }
+
+ /**
+ * 数组类型不是数值类型,直接调用父接口默认实现。
+ *
+ * @return 总为 false
+ */
+ @Override
+ public boolean isNumeric() {
+ return Type.super.isNumeric();
+ }
+
+ /**
+ * 判断两个 ArrayType 是否等价(元素类型完全一致即视为等价)。
+ *
+ * @param o 比较对象
+ * @return 是否等价
+ */
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ArrayType(Type type) && Objects.equals(elementType, type);
+ }
+
+ /**
+ * 返回数组类型的字符串描述,如 "int[]"。
+ *
+ * @return 类型名称
+ */
+ @Override
+ public String toString() {
+ return name();
+ }
+
+ /**
+ * 获取数组类型的名称描述,如 "int[]"。
+ *
+ * @return 类型名称
+ */
+ @Override
+ public String name() {
+ return elementType.name() + "[]";
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java
index fc7798f..209e578 100644
--- a/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java
@@ -47,4 +47,6 @@ public interface Type {
int ia = order.indexOf(a), ib = order.indexOf(b);
return order.get(Math.max(ia, ib));
}
+ /** 类型名字符串(如 int、double[]) */
+ default String name() { return toString(); }
}
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
index 1386018..3223860 100644
--- 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
@@ -6,42 +6,82 @@ 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.
+ * The {@code RPushCommand} class implements the {@link Command} interface
+ * and represents the "reference push" instruction ({@code R_PUSH}) in the virtual machine.
*
*
- * This instruction pushes a reference object, such as a String literal, onto the operand stack.
+ * This instruction pushes a reference value—typically a string literal or an array literal—onto the operand stack.
*
*
- * Instruction format: {@code R_PUSH }
+ * Instruction format: {@code R_PUSH }
*
- * - {@code }: The reference value (e.g., string) to be pushed onto the stack.
- * If the literal contains spaces, all parts after {@code R_PUSH} are joined into a single string.
+ * - {@code }: The reference value (e.g., string, boolean, integer, floating-point, or array literal)
+ * to be pushed onto the stack. If the literal contains spaces, all arguments after {@code R_PUSH} are joined with spaces.
*
*
- * Behavior:
+ * Behavior:
*
- * - Checks that the instruction has at least one parameter after the operator.
- * - Concatenates all parameters after {@code R_PUSH} into a single string (separated by spaces).
- * - Pushes the resulting string as a reference object onto the operand stack.
- * - Increments the program counter to the next instruction.
- * - Throws an {@code IllegalStateException} if the instruction is missing required parameters.
+ * - Ensures that at least one parameter is provided after the operator; otherwise, throws {@code IllegalStateException}.
+ * - Concatenates all parameters after {@code R_PUSH} into a single string, separated by spaces.
+ * - If the resulting string is an array literal (i.e., surrounded by square brackets), splits and parses its elements using {@link #getObject(String)} for primitive type support.
+ * - Otherwise, pushes the literal as a string reference onto the operand stack.
+ * - Increments the program counter to advance to the next instruction.
*
+ *
+ *
+ * Supported element types in array literals include integers, floating-point numbers, booleans,
+ * and quoted strings (surrounded by double quotes).
+ *
*/
public final class RPushCommand implements Command {
/**
- * Executes the {@code R_PUSH} instruction, pushing a reference (such as a string literal)
- * onto the operand stack.
+ * Parses a string element into its corresponding Java object.
+ *
+ * - If enclosed in double quotes, treats as a string literal (quotes are removed).
+ * - If "true" or "false" (case-insensitive), returns 1 or 0 respectively (as integer representation).
+ * - If numeric (integer or floating-point), parses accordingly.
+ * - Otherwise, returns the string as-is.
+ *
*
- * @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.
+ * @param e The string to parse.
+ * @return The parsed object (String, Integer, Double, or Integer for boolean).
+ */
+ private static Object getObject(String e) {
+ String x = e.trim();
+ Object v;
+ if (x.startsWith("\"") && x.endsWith("\"") && x.length() >= 2) {
+ // String literal (remove surrounding double quotes)
+ v = x.substring(1, x.length() - 1);
+ } else if ("true".equalsIgnoreCase(x) || "false".equalsIgnoreCase(x)) {
+ // Boolean value: true → 1, false → 0
+ v = Boolean.parseBoolean(x) ? 1 : 0;
+ } else {
+ try {
+ // Attempt to parse as floating-point or integer number
+ if (x.contains(".") || x.contains("e") || x.contains("E")) {
+ v = Double.parseDouble(x);
+ } else {
+ v = Integer.parseInt(x);
+ }
+ } catch (NumberFormatException ex) {
+ // Fallback: treat as plain string
+ v = x;
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Executes the {@code R_PUSH} instruction: pushes a reference value onto the operand stack.
+ *
+ * @param parts The instruction split into its components.
+ * @param pc The current program counter.
+ * @param stack The operand stack.
+ * @param lvs The local variable store (unused).
+ * @param cs The call stack (unused).
+ * @return The next program counter value.
+ * @throws IllegalStateException If no parameter is supplied after {@code R_PUSH}.
*/
@Override
public int execute(String[] parts, int pc,
@@ -52,12 +92,32 @@ public final class RPushCommand implements Command {
if (parts.length < 2)
throw new IllegalStateException("R_PUSH missing parameter");
+ // Join all arguments after R_PUSH into a single string, separated by spaces.
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());
+ String literal = sb.toString().trim();
+
+ // If the literal is an array (e.g., [1, 2, "foo"]), parse elements and push as an unmodifiable list.
+ if (literal.startsWith("[") && literal.endsWith("]")) {
+ String inside = literal.substring(1, literal.length() - 1).trim();
+ java.util.List