From bb5ba2218fcf6e293f2592b65b30a99750fbe943 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Wed, 25 Jun 2025 11:44:26 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E5=AD=97?= =?UTF-8?q?=E8=8A=82=E7=A0=81=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snow/compiler/backend/util/OpHelper.java | 34 +++++++++++++++++++ .../org/jcnc/snow/pkg/tasks/CompileTask.java | 10 ++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java index 8c7bba9..947512a 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java @@ -22,6 +22,11 @@ public final class OpHelper { */ private static final Map OPCODE_MAP; + /** + * opcode 字符串 → 指令名 的静态映射表 + */ + private static final Map OPCODE_NAME_MAP; + static { Map map = new HashMap<>(); map.put("I_ADD", Integer.toString(VMOpCode.I_ADD)); @@ -127,6 +132,13 @@ public final class OpHelper { map.put("RET", Integer.toString(VMOpCode.RET)); map.put("HALT", Integer.toString(VMOpCode.HALT)); OPCODE_MAP = Collections.unmodifiableMap(map); + + Map revmap = new HashMap<>(); // reverse map + OPCODE_MAP.forEach((key, value) -> { + revmap.put(Integer.parseInt(value), key); + }); + + OPCODE_NAME_MAP = Collections.unmodifiableMap(revmap); } /** @@ -170,5 +182,27 @@ public final class OpHelper { throw new IllegalStateException("Unknown const type: " + v.getClass()); } + /** + * 根据 opcode 数值的字符串形式获取指令名 + * @param code 字符串形式的 opcode 数值 + * @return opcode 对应的指令名 + */ + public static String opcodeName(String code) { + return opcodeName(Integer.parseInt(code)); + } + + /** + * 根据 opcode 获取指令名 + * @param code opcode + * @return opcode 对应的指令名 + */ + public static String opcodeName(int code) { + String name = OPCODE_NAME_MAP.get(code); + if (name == null) { + throw new IllegalStateException("Unknown opcode: " + name); + } + return name; + } + // endregion } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java b/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java index 04519d7..c76537b 100644 --- a/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java +++ b/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java @@ -1,7 +1,7 @@ package org.jcnc.snow.pkg.tasks; import org.jcnc.snow.cli.commands.CompileCommand; -import org.jcnc.snow.pkg.model.Project; +import org.jcnc.snow.compiler.backend.util.OpHelper; import org.jcnc.snow.compiler.backend.alloc.RegisterAllocator; import org.jcnc.snow.compiler.backend.builder.VMCodeGenerator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; @@ -18,6 +18,7 @@ import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.core.ParserEngine; import org.jcnc.snow.compiler.parser.function.ASTPrinter; import org.jcnc.snow.compiler.semantic.core.SemanticAnalyzerRunner; +import org.jcnc.snow.pkg.model.Project; import org.jcnc.snow.vm.VMLauncher; import java.nio.charset.StandardCharsets; @@ -198,7 +199,12 @@ public final class CompileTask implements Task { List finalCode = builder.build(); System.out.println("### VM code"); - finalCode.forEach(System.out::println); + for (int i = 0; i < finalCode.size(); i++) { + String[] parts = finalCode.get(i).split(" "); + String name = OpHelper.opcodeName(parts[0]); + parts = Arrays.copyOfRange(parts, 1, parts.length); + System.out.printf("%04d: %-10s %s\n", i, name, String.join(" ", parts)); + } // ---------------- 5. 写出 .water 文件 ---------------- Path outputFile = deriveOutputPath(sources, outputName, dir); From 6292cdc006f5f8896e6a269079fca600e870faf1 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Wed, 25 Jun 2025 11:46:14 +0800 Subject: [PATCH 2/8] =?UTF-8?q?style:=20=E8=AF=AD=E5=8F=A5=20lambda=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=B8=BA=E8=A1=A8=E8=BE=BE=E5=BC=8F=20lambda?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jcnc/snow/compiler/backend/util/OpHelper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java index 947512a..9d2e527 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java @@ -134,9 +134,7 @@ public final class OpHelper { OPCODE_MAP = Collections.unmodifiableMap(map); Map revmap = new HashMap<>(); // reverse map - OPCODE_MAP.forEach((key, value) -> { - revmap.put(Integer.parseInt(value), key); - }); + OPCODE_MAP.forEach((key, value) -> revmap.put(Integer.parseInt(value), key)); OPCODE_NAME_MAP = Collections.unmodifiableMap(revmap); } From 3f5dd92af982a3d78af6d453d3ed564bb8979517 Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 26 Jun 2025 12:14:47 +0800 Subject: [PATCH 3/8] =?UTF-8?q?style=EF=BC=9A=E8=B0=83=E6=95=B4=E9=97=B4?= =?UTF-8?q?=E8=B7=9D=20VMOpCode.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/engine/VMOpCode.java | 124 +++++++----------- 1 file changed, 47 insertions(+), 77 deletions(-) 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 5080fee..f5e8762 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java @@ -47,8 +47,8 @@ import org.jcnc.snow.vm.module.LocalVariableStore; *

Each opcode represents a specific operation executed by the virtual machine.

*/ public class VMOpCode { - // region 1. Arithmetic Operations (1–80) - // region 1.1 int32 (1-10) + // region 1. Arithmetic Operations (1–100) + // region 1.1 int32 (0-9) /** * I_ADD Opcode: Represents the int32 addition operation in the virtual machine. *

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

@@ -63,7 +63,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic int32 addition tasks.

*/ - public static final int I_ADD = 1; + public static final int I_ADD = 0; /** * I_SUB Opcode: Represents the int32 subtraction operation in the virtual machine. *

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

@@ -78,7 +78,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic int32 subtraction tasks.

*/ - public static final int I_SUB = 2; + public static final int I_SUB = 1; /** * I_MUL Opcode: Represents the int32 multiplication operation in the virtual machine. *

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

@@ -93,7 +93,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic int32 multiplication tasks.

*/ - public static final int I_MUL = 3; + public static final int I_MUL = 2; /** * I_DIV Opcode: Represents the int32 division operation in the virtual machine. *

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

@@ -109,7 +109,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic int32 division tasks.

*/ - public static final int I_DIV = 4; + public static final int I_DIV = 3; /** * I_MOD Opcode: Represents the int32 modulus (remainder) operation in the virtual machine. *

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

@@ -125,7 +125,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic int32 modulus (remainder) tasks.

*/ - public static final int I_MOD = 5; + public static final int I_MOD = 4; /** * I_INC Opcode: Represents the int32 increment operation for a local variable in the virtual machine. *

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

@@ -142,8 +142,7 @@ public class VMOpCode { * *

This opcode is particularly useful for optimizing scenarios where a local variable, such as a counter or loop index, is frequently incremented.

*/ - public static final int I_INC = 6; - + public static final int I_INC = 5; /** * I_NEG Opcode: Represents the int32 negation operation in the virtual machine. *

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

@@ -157,10 +156,10 @@ public class VMOpCode { * *

This opcode is typically used to negate an int32 value, making it a fundamental operation for arithmetic logic within the virtual machine.

*/ - public static final int I_NEG = 7; - + public static final int I_NEG = 6; // endregion - // region 1.2 long64 (11-20) + + // region 1.2 long64 (10-19) /** * L_ADD Opcode: Represents the long64 addition operation in the virtual machine. *

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

@@ -175,8 +174,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic long64 addition tasks.

*/ - public static final int L_ADD = 11; - + public static final int L_ADD = 10; /** * L_SUB Opcode: Represents the long64 subtraction operation in the virtual machine. *

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

@@ -191,8 +189,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic long64 subtraction tasks.

*/ - public static final int L_SUB = 12; - + public static final int L_SUB = 11; /** * L_MUL Opcode: Represents the long64 multiplication operation in the virtual machine. *

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

@@ -207,8 +204,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic long64 multiplication tasks.

*/ - public static final int L_MUL = 13; - + public static final int L_MUL = 12; /** * L_DIV Opcode: Represents the long64 division operation in the virtual machine. *

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

@@ -224,8 +220,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic long64 division tasks.

*/ - public static final int L_DIV = 14; - + public static final int L_DIV = 13; /** * L_MOD Opcode: Represents the long64 modulus (remainder) operation in the virtual machine. *

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

@@ -241,8 +236,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic long64 modulus (remainder) tasks.

*/ - public static final int L_MOD = 15; - + public static final int L_MOD = 14; /** * L_INC Opcode: Represents the long64 increment operation for a local variable in the virtual machine. *

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

@@ -259,9 +253,7 @@ public class VMOpCode { * *

This opcode is particularly useful for optimizing scenarios where a local `long64` variable, such as a counter or loop index, is frequently incremented.

*/ - public static final int L_INC = 16; - - + public static final int L_INC = 15; /** * L_NEG Opcode: Represents the long64 negation operation in the virtual machine. *

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

@@ -275,10 +267,10 @@ public class VMOpCode { * *

This opcode is typically used to negate a long64 value, making it a fundamental operation for arithmetic logic within the virtual machine.

*/ - public static final int L_NEG = 17; - + public static final int L_NEG = 16; // endregion - // region 1.3 short16 (21-30) + + // region 1.3 short16 (20-29) /** * S_ADD Opcode: Represents the short16 addition operation in the virtual machine. *

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

@@ -293,8 +285,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic short16 addition tasks.

*/ - public static final int S_ADD = 21; - + public static final int S_ADD = 20; /** * S_SUB Opcode: Represents the short16 subtraction operation in the virtual machine. *

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

@@ -309,8 +300,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic short16 subtraction tasks.

*/ - public static final int S_SUB = 22; - + public static final int S_SUB = 21; /** * S_MUL Opcode: Represents the short16 multiplication operation in the virtual machine. *

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

@@ -325,8 +315,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic short16 multiplication tasks.

*/ - public static final int S_MUL = 23; - + public static final int S_MUL = 22; /** * S_DIV Opcode: Represents the short16 division operation in the virtual machine. *

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

@@ -342,8 +331,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic short16 division tasks.

*/ - public static final int S_DIV = 24; - + public static final int S_DIV = 23; /** * S_MOD Opcode: Represents the short16 modulus (remainder) operation in the virtual machine. *

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

@@ -359,8 +347,7 @@ public class VMOpCode { *

This opcode is a fundamental arithmetic operation within the virtual machine's instruction set, * primarily used to handle basic short16 modulus (remainder) tasks.

*/ - public static final int S_MOD = 25; - + public static final int S_MOD = 24; /** * S_INC Opcode: Represents the short16 increment operation in the virtual machine. *

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

@@ -378,8 +365,7 @@ public class VMOpCode { *

This opcode is useful for scenarios where a local variable needs to be incremented, such as counters within loops, * or for optimizing the modification of variables in tight loops.

*/ - public static final int S_INC = 26; - + public static final int S_INC = 25; /** * S_NEG Opcode: Represents the short16 negation operation in the virtual machine. *

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

@@ -393,9 +379,9 @@ public class VMOpCode { * *

This opcode is typically used to negate a short16 value, making it a fundamental operation for arithmetic logic within the virtual machine.

*/ - public static final int S_NEG = 27; - + public static final int S_NEG = 26; // endregion + // region 1.4 byte8 (31-40) /** * B_ADD Opcode: Represents the byte8 addition operation in the virtual machine. @@ -412,7 +398,6 @@ public class VMOpCode { * primarily used to handle basic byte8 addition tasks.

*/ public static final int B_ADD = 31; - /** * B_SUB Opcode: Represents the byte8 subtraction operation in the virtual machine. *

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

@@ -428,7 +413,6 @@ public class VMOpCode { * primarily used to handle basic byte8 subtraction tasks.

*/ public static final int B_SUB = 32; - /** * B_MUL Opcode: Represents the byte8 multiplication operation in the virtual machine. *

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

@@ -444,7 +428,6 @@ public class VMOpCode { * primarily used to handle basic byte8 multiplication tasks.

*/ public static final int B_MUL = 33; - /** * B_DIV Opcode: Represents the byte8 division operation in the virtual machine. *

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

@@ -461,7 +444,6 @@ public class VMOpCode { * primarily used to handle basic byte8 division tasks.

*/ public static final int B_DIV = 34; - /** * B_MOD Opcode: Represents the byte8 modulus (remainder) operation in the virtual machine. *

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

@@ -478,7 +460,6 @@ public class VMOpCode { * primarily used to handle basic byte8 modulus (remainder) tasks.

*/ public static final int B_MOD = 35; - /** * B_INC Opcode: Represents the byte8 increment operation for a local variable in the virtual machine. *

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

@@ -496,8 +477,6 @@ public class VMOpCode { *

This opcode is particularly useful for optimizing scenarios where a local `byte8` variable, such as a counter or loop index, is frequently incremented.

*/ public static final int B_INC = 36; - - /** * B_NEG Opcode: Represents the byte8 negation operation in the virtual machine. *

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

@@ -512,8 +491,8 @@ public class VMOpCode { *

This opcode is typically used to negate a byte8 value, making it a fundamental operation for arithmetic logic within the virtual machine.

*/ public static final int B_NEG = 37; - // endregion + // region 1.5 double64 (41-50) /** * D_ADD Opcode: Represents the double64 precision floating-point addition operation in the virtual machine. @@ -530,7 +509,6 @@ public class VMOpCode { * primarily used to handle basic double64 precision floating-point addition tasks.

*/ public static final int D_ADD = 41; - /** * D_SUB Opcode: Represents the double64 precision floating-point subtraction operation in the virtual machine. *

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

@@ -546,7 +524,6 @@ public class VMOpCode { * primarily used to handle basic double64 precision floating-point subtraction tasks.

*/ public static final int D_SUB = 42; - /** * D_MUL Opcode: Represents the double64 precision floating-point multiplication operation in the virtual machine. *

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

@@ -562,7 +539,6 @@ public class VMOpCode { * primarily used to handle basic double64 precision floating-point multiplication tasks.

*/ public static final int D_MUL = 43; - /** * D_DIV Opcode: Represents the double64 precision floating-point division operation in the virtual machine. *

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

@@ -579,7 +555,6 @@ public class VMOpCode { * primarily used to handle basic double64 precision floating-point division tasks.

*/ public static final int D_DIV = 44; - /** * D_MOD Opcode: Represents the double64 precision floating-point modulus (remainder) operation in the virtual machine. *

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

@@ -596,7 +571,6 @@ public class VMOpCode { * primarily used to handle basic double64 precision floating-point modulus (remainder) tasks.

*/ public static final int D_MOD = 45; - /** * D_INC Opcode: Represents the double64 increment operation for a local variable in the virtual machine. *

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

@@ -614,7 +588,6 @@ public class VMOpCode { *

This opcode is particularly useful for optimizing scenarios where a local `double64` variable, such as a counter or loop index, is frequently incremented.

*/ public static final int D_INC = 46; - /** * D_NEG Opcode: Represents the double64 precision floating-point negation operation in the virtual machine. *

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

@@ -629,8 +602,8 @@ public class VMOpCode { *

This opcode is typically used to negate a double64 precision floating-point value, making it a fundamental operation for double64 precision arithmetic logic within the virtual machine.

*/ public static final int D_NEG = 47; - // endregion + // region 1.6 float32 (51-60) /** * F_ADD Opcode: Represents the float32 addition operation in the virtual machine. @@ -726,7 +699,6 @@ public class VMOpCode { *

This opcode is particularly useful for optimizing scenarios where a local `float32` variable, such as a counter or loop index, is frequently incremented.

*/ public static final int F_INC = 56; - /** * F_NEG Opcode: Represents the float32 negation operation in the virtual machine. *

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

@@ -741,7 +713,10 @@ public class VMOpCode { *

This opcode is typically used to negate a float32 value, making it a fundamental operation for float32 arithmetic logic within the virtual machine.

*/ public static final int F_NEG = 57; + // endregion + // endregion + // region 2. Type Conversion Operation /** * I2L Opcode: Represents the type conversion operation from int32 to long64 in the virtual machine. *

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

@@ -756,7 +731,6 @@ public class VMOpCode { *

This opcode is commonly used to widen an int32 value to a long64 type to accommodate larger numeric ranges.

*/ public static final int I2L = 61; - /** * I2S Opcode: Represents the type conversion operation from int32 to short16 in the virtual machine. *

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

@@ -771,7 +745,6 @@ public class VMOpCode { *

This opcode is typically used to narrow an int32 value to a short16 type when a smaller data representation is needed.

*/ public static final int I2S = 62; - /** * I2B Opcode: Represents the type conversion operation from int32 to byte8 in the virtual machine. *

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

@@ -786,7 +759,6 @@ public class VMOpCode { *

This opcode is used to narrow an int32 value to a byte8 type, suitable when a smaller numeric type is required.

*/ public static final int I2B = 63; - /** * I2D Opcode: Represents the type conversion operation from int32 to double64 in the virtual machine. *

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

@@ -801,7 +773,6 @@ public class VMOpCode { *

This opcode is used to widen an int32 value to a double64 type, providing high-precision floating-point calculations.

*/ public static final int I2D = 64; - /** * I2F Opcode: Represents the type conversion operation from int32 to float32 in the virtual machine. *

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

@@ -816,7 +787,6 @@ public class VMOpCode { *

This opcode is used to convert an int32 value to a float32 type when floating-point arithmetic is required.

*/ public static final int I2F = 65; - /** * L2I Opcode: Represents the type conversion operation from long64 to int32 in the virtual machine. *

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

@@ -831,7 +801,6 @@ public class VMOpCode { *

This opcode is typically used to narrow a long64 value to an int32 type for further integer operations.

*/ public static final int L2I = 66; - /** * L2D Opcode: Represents the type conversion operation from long64 to double64 in the virtual machine. *

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

@@ -981,9 +950,8 @@ public class VMOpCode { *

This opcode is used to widen a byte8 value to an int32 type to ensure compatibility with integer-based operations.

*/ public static final int B2I = 76; + // endregion - // endregion - // endregion // region 2. Bitwise Operations (81–90) // region 2.1 int32 (81-85) /** @@ -1507,6 +1475,8 @@ public class VMOpCode { * */ public static final int F_PUSH = 116; + // endregion + // region 4.2 POP (121-125) /** * I_POP Opcode: Represents a stack operation that removes the top element from the operand stack. *

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

@@ -1525,10 +1495,9 @@ public class VMOpCode { *
  • Ensuring stack balance during function calls or control flow transitions.
  • * */ - - // endregion - // region 4.2 POP (121-125) public static final int POP = 121; + // endregion + // region 4.3 DUP (126-130) /** * DUP Opcode: Represents a stack operation that duplicates the top element of the operand stack. *

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

    @@ -1547,9 +1516,11 @@ public class VMOpCode { *
  • Managing stack balance when performing operations that require repeated access to the same data.
  • * */ - // endregion - // region 4.3 DUP (126-130) + public static final int DUP = 126; + // endregion + + // region 4.4 SWAP (131-135) /** * SWAP Opcode: Represents a stack operation that swaps the top two values of the operand stack. *

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

    @@ -1569,12 +1540,9 @@ public class VMOpCode { *
  • Ensuring proper operand placement for later instructions that depend on the order of stack elements.
  • * */ - - // endregion - // region 4.4 SWAP (131-135) public static final int SWAP = 131; - // endregion + // endregion // region 5. Memory Operations (151–166) /** @@ -1818,7 +1786,7 @@ public class VMOpCode { * */ public static final int F_LOAD = 166; - // endregion + /** * MOV Opcode: Represents a move operation that transfers a value from one local variable to another within the local variable store. *

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

    @@ -1839,7 +1807,8 @@ public class VMOpCode { * */ public static final int MOV = 171; - // region 6. function call + // endregion + // region 6. Function Call /** * CALL Opcode: Represents a function or subroutine call operation that transfers control to a specified function address. *

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

    @@ -1898,6 +1867,7 @@ public class VMOpCode { */ public static final int HALT = 255; // endregion + /** * Default constructor for creating an instance of VMOpCode. * This constructor is empty as no specific initialization is required. From c17ccc7540c791e4f9a585f533bb66387aa1cc47 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Thu, 26 Jun 2025 19:03:51 +0800 Subject: [PATCH 4/8] =?UTF-8?q?style:=20=E5=8C=85=E5=90=8D=20org.jcnc.snow?= =?UTF-8?q?.compiler.backend.util=20=E5=90=8E=E9=9D=A2=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snow/compiler/backend/generator/BinaryOpGenerator.java | 4 ++-- .../jcnc/snow/compiler/backend/generator/CallGenerator.java | 2 +- .../snow/compiler/backend/generator/CmpJumpGenerator.java | 4 ++-- .../jcnc/snow/compiler/backend/generator/JumpGenerator.java | 2 +- .../snow/compiler/backend/generator/LoadConstGenerator.java | 2 +- .../jcnc/snow/compiler/backend/generator/ReturnGenerator.java | 2 +- .../snow/compiler/backend/generator/UnaryOpGenerator.java | 4 ++-- .../snow/compiler/backend/{util => utils}/IROpCodeMapper.java | 2 +- .../jcnc/snow/compiler/backend/{util => utils}/OpHelper.java | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/org/jcnc/snow/compiler/backend/{util => utils}/IROpCodeMapper.java (99%) rename src/main/java/org/jcnc/snow/compiler/backend/{util => utils}/OpHelper.java (99%) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/BinaryOpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/BinaryOpGenerator.java index 91a4d91..0d0a983 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/BinaryOpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/BinaryOpGenerator.java @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.backend.generator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; -import org.jcnc.snow.compiler.backend.util.IROpCodeMapper; -import org.jcnc.snow.compiler.backend.util.OpHelper; +import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.core.IRValue; import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction; import org.jcnc.snow.compiler.ir.value.IRConstant; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java index ff6961b..d455a4b 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/CallGenerator.java @@ -2,7 +2,7 @@ package org.jcnc.snow.compiler.backend.generator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; -import org.jcnc.snow.compiler.backend.util.OpHelper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.instruction.CallInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; 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 e6a3e28..57437b4 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 @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.util.IROpCodeMapper; -import org.jcnc.snow.compiler.backend.util.OpHelper; +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.ir.instruction.IRCompareJumpInstruction; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java index 85d2907..c8426b3 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java @@ -1,6 +1,6 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.util.OpHelper; +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.ir.instruction.IRJumpInstruction; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java index 9e75f22..760422a 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java @@ -2,7 +2,7 @@ package org.jcnc.snow.compiler.backend.generator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; -import org.jcnc.snow.compiler.backend.util.OpHelper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction; import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/ReturnGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/ReturnGenerator.java index a58af50..6a48847 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/ReturnGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/ReturnGenerator.java @@ -2,7 +2,7 @@ package org.jcnc.snow.compiler.backend.generator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; -import org.jcnc.snow.compiler.backend.util.OpHelper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.instruction.ReturnInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java index 46d1f53..a3de573 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.util.IROpCodeMapper; -import org.jcnc.snow.compiler.backend.util.OpHelper; +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.ir.instruction.UnaryOperationInstruction; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java b/src/main/java/org/jcnc/snow/compiler/backend/utils/IROpCodeMapper.java similarity index 99% rename from src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java rename to src/main/java/org/jcnc/snow/compiler/backend/utils/IROpCodeMapper.java index f2d2997..31c0033 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/utils/IROpCodeMapper.java @@ -1,4 +1,4 @@ -package org.jcnc.snow.compiler.backend.util; +package org.jcnc.snow.compiler.backend.utils; import org.jcnc.snow.compiler.ir.core.IROpCode; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java similarity index 99% rename from src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java rename to src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java index 8c7bba9..9328218 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/util/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java @@ -1,4 +1,4 @@ -package org.jcnc.snow.compiler.backend.util; +package org.jcnc.snow.compiler.backend.utils; import org.jcnc.snow.vm.engine.VMOpCode; From c03761ed610fa6df9502091b08ce0a2f87102224 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Thu, 26 Jun 2025 20:39:54 +0800 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20byte=E3=80=81short=20=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E5=90=8E=E4=BC=9A=E5=8F=98=E4=B8=BA=20int=20=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jcnc/snow/vm/commands/arithmetic/byte8/BAddCommand.java | 2 +- .../jcnc/snow/vm/commands/arithmetic/byte8/BDivCommand.java | 2 +- .../jcnc/snow/vm/commands/arithmetic/byte8/BModCommand.java | 2 +- .../jcnc/snow/vm/commands/arithmetic/byte8/BMulCommand.java | 2 +- .../jcnc/snow/vm/commands/arithmetic/byte8/BSubCommand.java | 2 +- .../snow/vm/commands/arithmetic/short16/SAddCommand.java | 6 +++--- .../snow/vm/commands/arithmetic/short16/SDivCommand.java | 2 +- .../snow/vm/commands/arithmetic/short16/SModCommand.java | 2 +- .../snow/vm/commands/arithmetic/short16/SMulCommand.java | 2 +- .../snow/vm/commands/arithmetic/short16/SSubCommand.java | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BAddCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BAddCommand.java index b05f809..f2a42ca 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BAddCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BAddCommand.java @@ -50,7 +50,7 @@ public class BAddCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the addition and push the result back onto the stack - operandStack.push(a + b); + operandStack.push((byte)(a + b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BDivCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BDivCommand.java index ad24912..582951b 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BDivCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BDivCommand.java @@ -56,7 +56,7 @@ public class BDivCommand implements Command { } // Perform the division and push the result back onto the stack - operandStack.push(a / b); + operandStack.push((byte)(a / b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BModCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BModCommand.java index 88b12bd..dd5892f 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BModCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BModCommand.java @@ -50,7 +50,7 @@ public class BModCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the modulus operation and push the result back onto the stack - operandStack.push(a % b); + operandStack.push((byte)(a % b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BMulCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BMulCommand.java index e5de63a..0c6d9c3 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BMulCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BMulCommand.java @@ -50,7 +50,7 @@ public class BMulCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the multiplication and push the result back onto the stack - operandStack.push(a * b); + operandStack.push((byte)(a * b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BSubCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BSubCommand.java index 091cafd..4c7957e 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BSubCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/byte8/BSubCommand.java @@ -50,7 +50,7 @@ public class BSubCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the subtraction and push the result back onto the stack - operandStack.push(a - b); + operandStack.push((byte)(a - b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SAddCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SAddCommand.java index 4137a01..b4b1290 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SAddCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SAddCommand.java @@ -46,11 +46,11 @@ public class SAddCommand implements Command { @Override public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { // Pop the top two operands from the stack - Short b = (Short) operandStack.pop(); - Short a = (Short) operandStack.pop(); + short b = (short) operandStack.pop(); + short a = (short) operandStack.pop(); // Perform the addition and push the result back onto the stack - operandStack.push(a + b); + operandStack.push((short)(a + b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SDivCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SDivCommand.java index f14cefa..9c71b8c 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SDivCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SDivCommand.java @@ -56,7 +56,7 @@ public class SDivCommand implements Command { } // Perform the division and push the result back onto the stack - operandStack.push(a / b); + operandStack.push((short)(a / b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SModCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SModCommand.java index 0047449..105b5bc 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SModCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SModCommand.java @@ -50,7 +50,7 @@ public class SModCommand implements Command { short a = (short) operandStack.pop(); // Perform the modulus operation and push the result back onto the stack - operandStack.push(a % b); + operandStack.push((short)(a % b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SMulCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SMulCommand.java index 1a2ac4e..f6c022d 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SMulCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SMulCommand.java @@ -50,7 +50,7 @@ public class SMulCommand implements Command { short a = (short) operandStack.pop(); // Perform the multiplication and push the result back onto the stack - operandStack.push(a * b); + operandStack.push((short)(a * b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SSubCommand.java b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SSubCommand.java index 66c3295..53953b3 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SSubCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/arithmetic/short16/SSubCommand.java @@ -50,7 +50,7 @@ public class SSubCommand implements Command { short a = (short) operandStack.pop(); // Perform the subtraction and push the result back onto the stack - operandStack.push(a - b); + operandStack.push((short)(a - b)); // Return the updated program counter (next instruction) return currentPC + 1; From 8b421d3c92316020476c749f4a7be9b653c98dc2 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Fri, 27 Jun 2025 13:13:41 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=E8=AF=AD=E4=B9=89=E5=88=86=E6=9E=90?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E6=98=BE=E7=A4=BA=E6=9C=AA=E7=9F=A5=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/ir/builder/IRProgramBuilder.java | 10 ++++- .../compiler/parser/ast/AssignmentNode.java | 11 +++++- .../parser/ast/BinaryExpressionNode.java | 13 ++++++- .../parser/ast/CallExpressionNode.java | 1 + .../compiler/parser/ast/DeclarationNode.java | 39 ++++++++++++++++++- .../parser/ast/ExpressionStatementNode.java | 10 ++++- .../compiler/parser/ast/FunctionNode.java | 14 ++++++- .../compiler/parser/ast/IdentifierNode.java | 10 ++++- .../jcnc/snow/compiler/parser/ast/IfNode.java | 8 +++- .../snow/compiler/parser/ast/ImportNode.java | 10 ++++- .../snow/compiler/parser/ast/LoopNode.java | 14 ++++++- .../parser/ast/MemberExpressionNode.java | 11 +++++- .../snow/compiler/parser/ast/ModuleNode.java | 12 +++++- .../compiler/parser/ast/ParameterNode.java | 11 +++++- .../snow/compiler/parser/ast/ReturnNode.java | 39 ++++++++++++++++++- .../parser/ast/UnaryExpressionNode.java | 12 +++++- .../expression/BinaryOperatorParselet.java | 7 +++- .../parser/expression/CallParselet.java | 12 +++--- .../parser/expression/IdentifierParselet.java | 7 +++- .../parser/expression/MemberParselet.java | 7 +++- .../expression/UnaryOperatorParselet.java | 7 +++- .../parser/function/FunctionParser.java | 23 ++++++++--- .../compiler/parser/module/ImportParser.java | 7 +++- .../compiler/parser/module/ModuleParser.java | 7 +++- .../statement/DeclarationStatementParser.java | 7 +++- .../statement/ExpressionStatementParser.java | 9 ++++- .../parser/statement/IfStatementParser.java | 7 +++- .../parser/statement/LoopStatementParser.java | 14 ++++++- .../statement/ReturnStatementParser.java | 7 +++- 29 files changed, 303 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java index a1168ec..5513fdc 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java @@ -76,6 +76,14 @@ public final class IRProgramBuilder { * @return 生成的 FunctionNode,用于后续 IRFunction 构建 */ private FunctionNode wrapTopLevel(StatementNode stmt) { - return new FunctionNode("_start", null, String.valueOf(List.of()), List.of(stmt)); + return new FunctionNode( + "_start", + null, + String.valueOf(List.of()), + List.of(stmt), + -1, + -1, + "" + ); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java index 69781b9..eace610 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java @@ -16,8 +16,17 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; * * @param variable 左值变量名(即赋值目标) * @param value 表达式右值(即赋值来源) + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record AssignmentNode(String variable, ExpressionNode value) implements StatementNode { +public record AssignmentNode( + String variable, + ExpressionNode value, + int line, + int column, + String file +) implements StatementNode { /** * 返回赋值语句的字符串形式,便于调试与日志输出。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java index 6e49e63..40412de 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java @@ -12,9 +12,18 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * @param left 左操作数(子表达式) * @param operator 运算符字符串(如 "+", "-", "*", "/" 等) * @param right 右操作数(子表达式) + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record BinaryExpressionNode(ExpressionNode left, String operator, - ExpressionNode right) implements ExpressionNode { +public record BinaryExpressionNode( + ExpressionNode left, + String operator, + ExpressionNode right, + int line, + int column, + String file +) implements ExpressionNode { /** * 返回该二元运算表达式的字符串表示形式。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java index ac36871..22f47bc 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java @@ -14,6 +14,7 @@ import java.util.List; * @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。 * @param line 当前表达式所在的行号,方便调试和错误定位。 * @param column 当前表达式所在的列号,用于精确定位错误位置。 + * @param file 当前表达式所在的文件,用于错误定位。 */ public record CallExpressionNode( ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java index 1819d1f..9e1edf5 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java @@ -23,6 +23,15 @@ public class DeclarationNode implements StatementNode { /** 可选的初始化表达式 */ private final Optional initializer; + /** 当前节点所在的行号 **/ + private final int line; + + /** 当前节点所在的列号 **/ + private final int column; + + /** 当前节点所在的文件 **/ + private final String file; + /** * 构造一个 {@code DeclarationNode} 实例。 * @@ -30,10 +39,13 @@ public class DeclarationNode implements StatementNode { * @param type 变量类型字符串(如 "int"、"string") * @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化 */ - public DeclarationNode(String name, String type, ExpressionNode initializer) { + public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) { this.name = name; this.type = type; this.initializer = Optional.ofNullable(initializer); + this.line = line; + this.column = column; + this.file = file; } /** @@ -62,4 +74,29 @@ public class DeclarationNode implements StatementNode { public Optional getInitializer() { return initializer; } + + /** + * 获取当前表达式所在的行号。 + * + * @return 当前表达式的行号。 + */ + public int line() { + return line; + } + + /** + * 获取当前表达式所在的列号。 + * + * @return 当前表达式的列号。 + */ + public int column() { + return column; + } + + /** + * 获取当前表达式所在的文件名。 + * + * @return 当前表达式所在的文件名。 + */ + public String file() { return file; } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java index cf62fb1..1a2f7a5 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java @@ -11,6 +11,14 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; *

    * * @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。 + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record ExpressionStatementNode(ExpressionNode expression) implements StatementNode { +public record ExpressionStatementNode( + ExpressionNode expression, + int line, + int column, + String file +) implements StatementNode { } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java index 7ab55dd..29ab884 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java @@ -17,7 +17,17 @@ import java.util.List; * @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义 * @param returnType 函数的返回类型(如 "int"、"void" 等) * @param body 函数体语句块,由一组 {@link StatementNode} 构成 + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record FunctionNode(String name, List parameters, String returnType, - List body) implements Node { +public record FunctionNode( + String name, + List parameters, + String returnType, + List body, + int line, + int column, + String file +) implements Node { } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java index cfce3d4..de0ed17 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java @@ -10,8 +10,16 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

    * * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record IdentifierNode(String name) implements ExpressionNode { +public record IdentifierNode( + String name, + int line, + int column, + String file +) implements ExpressionNode { /** * 返回标识符节点的字符串形式,通常为其名称本身。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java index 9ac9371..a26c8e2 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java @@ -29,10 +29,16 @@ import java.util.List; * @param condition 控制分支执行的条件表达式 * @param thenBranch 条件为 true 时执行的语句块 * @param elseBranch 条件为 false 时执行的语句块(可为空) + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ public record IfNode( ExpressionNode condition, List thenBranch, - List elseBranch + List elseBranch, + int line, + int column, + String file ) implements StatementNode { } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java index f551fd9..c6b65e9 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java @@ -14,6 +14,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; *

    * * @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils") + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record ImportNode(String moduleName) implements Node { +public record ImportNode( + String moduleName, + int line, + int column, + String file +) implements Node { } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java index 7821ae4..a8ddbe1 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java @@ -17,7 +17,17 @@ import java.util.List; * @param condition 每次迭代前评估的条件表达式,控制循环是否继续 * @param update 每轮迭代完成后执行的更新语句 * @param body 循环体语句列表,表示循环主体执行逻辑 + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record LoopNode(StatementNode initializer, ExpressionNode condition, StatementNode update, - List body) implements StatementNode { +public record LoopNode( + StatementNode initializer, + ExpressionNode condition, + StatementNode update, + List body, + int line, + int column, + String file +) implements StatementNode { } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java index 7b49db3..d0ac38e 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java @@ -11,8 +11,17 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * * @param object 左侧对象表达式,表示成员所属的作用域或容器 * @param member 要访问的成员名称(字段名或方法名) + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record MemberExpressionNode(ExpressionNode object, String member) implements ExpressionNode { +public record MemberExpressionNode( + ExpressionNode object, + String member, + int line, + int column, + String file +) implements ExpressionNode { /** * 返回成员访问表达式的字符串形式。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java index 564402a..05d47de 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java @@ -13,8 +13,18 @@ import java.util.StringJoiner; * @param name 模块名称。 * @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。 * @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。 + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record ModuleNode(String name, List imports, List functions) implements Node { +public record ModuleNode( + String name, + List imports, + List functions, + int line, + int column, + String file +) implements Node { /** * 返回模块节点的字符串表示形式,包含模块名、导入模块列表和函数列表。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ParameterNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ParameterNode.java index 91e93aa..0fbdc18 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ParameterNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ParameterNode.java @@ -11,8 +11,17 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; * * @param name 参数名称标识符 * @param type 参数类型字符串(如 "int"、"string") + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record ParameterNode(String name, String type) implements Node { +public record ParameterNode( + String name, + String type, + int line, + int column, + String file +) implements Node { /** * 返回参数的字符串形式,格式为 {@code name:type}。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ReturnNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ReturnNode.java index 28143dd..0fc2254 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ReturnNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ReturnNode.java @@ -23,13 +23,25 @@ public class ReturnNode implements StatementNode { /** 可选的返回值表达式 */ private final Optional expression; + /** 当前节点所在的行号 **/ + private final int line; + + /** 当前节点所在的列号 **/ + private final int column; + + /** 当前节点所在的文件 **/ + private final String file; + /** * 构造一个 {@code ReturnNode} 实例。 * * @param expression 返回值表达式,如果无返回值则可为 {@code null} */ - public ReturnNode(ExpressionNode expression) { + public ReturnNode(ExpressionNode expression, int line, int column, String file) { this.expression = Optional.ofNullable(expression); + this.line = line; + this.column = column; + this.file = file; } /** @@ -40,4 +52,29 @@ public class ReturnNode implements StatementNode { public Optional getExpression() { return expression; } + + /** + * 获取当前表达式所在的行号。 + * + * @return 当前表达式的行号。 + */ + public int line() { + return line; + } + + /** + * 获取当前表达式所在的列号。 + * + * @return 当前表达式的列号。 + */ + public int column() { + return column; + } + + /** + * 获取当前表达式所在的文件名。 + * + * @return 当前表达式所在的文件名。 + */ + public String file() { return file; } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java index d956fc8..7e38ebc 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java @@ -15,9 +15,17 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * * @param operator 一元运算符(仅 "-" 或 "!") * @param operand 运算对象 / 右操作数 + * @param line 当前节点所在的行号 + * @param column 当前节点所在的列号 + * @param file 当前节点所在的文件 */ -public record UnaryExpressionNode(String operator, - ExpressionNode operand) implements ExpressionNode { +public record UnaryExpressionNode( + String operator, + ExpressionNode operand, + int line, + int column, + String file +) implements ExpressionNode { /** * 生成调试友好的字符串表示,例如 {@code "-x"} 或 {@code "!flag"}。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java index da86f01..adee8bd 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java @@ -37,6 +37,11 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i */ @Override public ExpressionNode parse(ParserContext ctx, ExpressionNode left) { + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + Token op = ctx.getTokens().next(); int prec = precedence.ordinal(); @@ -46,7 +51,7 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1] ); - return new BinaryExpressionNode(left, op.getLexeme(), right); + return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java index 9499f6d..9f5478a 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java @@ -26,14 +26,15 @@ public class CallParselet implements InfixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, ExpressionNode left) { + // 获取函数名 token 的行号、列号和文件名 + int line = ctx.getTokens().peek(-1).getLine(); + int column = ctx.getTokens().peek(-1).getCol(); + String file = ctx.getSourceName(); + ctx.getTokens().next(); // 消费 "(" List args = new ArrayList<>(); - // 获取当前 token 的行号和列号 - int line = ctx.getTokens().peek().getLine(); - int column = ctx.getTokens().peek().getCol(); - // 解析函数调用参数 if (!ctx.getTokens().peek().getLexeme().equals(")")) { do { @@ -43,8 +44,7 @@ public class CallParselet implements InfixParselet { ctx.getTokens().expect(")"); // 消费并验证 ")" - // 创建 CallExpressionNode 并传递位置信息,文件名称 - String file = ctx.getSourceName(); + // 创建 CallExpressionNode 并传递位置信息 return new CallExpressionNode(left, args, line, column, file); } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java index 057c425..7e46337 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java @@ -24,6 +24,11 @@ public class IdentifierParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new IdentifierNode(token.getLexeme()); + // 获取标识符 token 的行号、列号和文件名 + int line = ctx.getTokens().peek(-1).getLine(); + int column = ctx.getTokens().peek(-1).getCol(); + String file = ctx.getSourceName(); + + return new IdentifierNode(token.getLexeme(), line, column, file); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java index b0f1e5f..ed3cd58 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java @@ -28,8 +28,13 @@ public class MemberParselet implements InfixParselet { TokenStream ts = ctx.getTokens(); ts.expect("."); // 消费点号 + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + String member = ts.expectType(TokenType.IDENTIFIER).getLexeme(); - return new MemberExpressionNode(left, member); + return new MemberExpressionNode(left, member, line, column, file); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java index abfa97a..5aedf93 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java @@ -41,6 +41,11 @@ public class UnaryOperatorParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + /* ------------------------------------------------------------ * 1. 以 UNARY 优先级递归解析操作数,避免错误结合顺序。 * ------------------------------------------------------------ */ @@ -50,6 +55,6 @@ public class UnaryOperatorParselet implements PrefixParselet { /* ------------------------------------------------------------ * 2. 封装成 AST 节点并返回。 * ------------------------------------------------------------ */ - return new UnaryExpressionNode(token.getLexeme(), operand); + return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java index af2251e..a7a3449 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java @@ -57,6 +57,11 @@ public class FunctionParser implements TopLevelParser { public FunctionNode parse(ParserContext ctx) { TokenStream ts = ctx.getTokens(); + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + parseFunctionHeader(ts); String functionName = parseFunctionName(ts); @@ -69,7 +74,7 @@ public class FunctionParser implements TopLevelParser { parseFunctionFooter(ts); - return new FunctionNode(functionName, parameters, returnType[0], body); + return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file); } /** @@ -92,7 +97,7 @@ public class FunctionParser implements TopLevelParser { map.put("parameter", new SectionDefinition( (TokenStream stream) -> stream.peek().getLexeme().equals("parameter"), - (ParserContext context, TokenStream stream) -> params.addAll(parseParameters(stream)) + (ParserContext context, TokenStream stream) -> params.addAll(parseParameters(context)) )); map.put("return_type", new SectionDefinition( @@ -154,10 +159,12 @@ public class FunctionParser implements TopLevelParser { * *

    * - * @param ts 当前使用的 {@link TokenStream}。 + * @param ctx 当前解析上下文,包含 {@link TokenStream} 和符号表等作用域信息。 * @return 所有参数节点的列表。 */ - private List parseParameters(TokenStream ts) { + private List parseParameters(ParserContext ctx) { + TokenStream ts = ctx.getTokens(); + ts.expect("parameter"); ts.expect(":"); skipComments(ts); @@ -175,13 +182,19 @@ public class FunctionParser implements TopLevelParser { if (lex.equals("return_type") || lex.equals("body") || lex.equals("end")) { break; } + + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + ts.expect("declare"); String pname = ts.expectType(TokenType.IDENTIFIER).getLexeme(); ts.expect(":"); String ptype = ts.expectType(TokenType.TYPE).getLexeme(); skipComments(ts); ts.expectType(TokenType.NEWLINE); - list.add(new ParameterNode(pname, ptype)); + list.add(new ParameterNode(pname, ptype, line, column, file)); } return list; } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java b/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java index 38dd788..d5443ac 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java @@ -46,13 +46,18 @@ public class ImportParser { // 解析一个或多个模块名(标识符),允许使用逗号分隔多个模块 do { + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 获取当前标识符类型的词法单元,并提取其原始词素 String mod = ctx.getTokens() .expectType(TokenType.IDENTIFIER) .getLexeme(); // 创建 ImportNode 节点并加入列表 - imports.add(new ImportNode(mod)); + imports.add(new ImportNode(mod, line, column, file)); } while (ctx.getTokens().match(",")); // 如果匹配到逗号,继续解析下一个模块名 // 最后必须匹配换行符,标志 import 语句的结束 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java b/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java index b696410..ac9e05d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java @@ -40,6 +40,11 @@ public class ModuleParser implements TopLevelParser { // 获取当前上下文中提供的词法流 TokenStream ts = ctx.getTokens(); + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 期望模块声明以关键字 "module:" 开始 ts.expect("module"); ts.expect(":"); @@ -90,6 +95,6 @@ public class ModuleParser implements TopLevelParser { ts.expect("module"); // 构建并返回完整的模块语法树节点 - return new ModuleNode(name, imports, functions); + return new ModuleNode(name, imports, functions, line, column, file); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java index b99d09c..2323ada 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java @@ -43,6 +43,11 @@ public class DeclarationStatementParser implements StatementParser { */ @Override public DeclarationNode parse(ParserContext ctx) { + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 声明语句必须以 "declare" 开头 ctx.getTokens().expect("declare"); @@ -69,6 +74,6 @@ public class DeclarationStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 返回构建好的声明语法树节点 - return new DeclarationNode(name, type, init); + return new DeclarationNode(name, type, init, line, column, file); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java index dd9df94..526dbf0 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java @@ -50,6 +50,11 @@ public class ExpressionStatementParser implements StatementParser { throw new IllegalStateException("Cannot parse expression starting with keyword: " + ts.peek().getLexeme()); } + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 处理赋值语句:格式为 identifier = expression if (ts.peek().getType() == TokenType.IDENTIFIER && ts.peek(1).getLexeme().equals("=")) { @@ -58,13 +63,13 @@ public class ExpressionStatementParser implements StatementParser { ts.expect("="); // 消耗等号 ExpressionNode value = new PrattExpressionParser().parse(ctx); // 解析表达式 ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束 - return new AssignmentNode(varName, value); // 返回赋值节点 + return new AssignmentNode(varName, value, line, column, file); // 返回赋值节点 } // 处理普通表达式语句,如函数调用、字面量、运算表达式等 ExpressionNode expr = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束 - return new ExpressionStatementNode(expr); // 返回表达式语句节点 + return new ExpressionStatementNode(expr, line, column, file); // 返回表达式语句节点 } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java index f0e2498..eda8bb1 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java @@ -47,6 +47,11 @@ public class IfStatementParser implements StatementParser { public IfNode parse(ParserContext ctx) { var ts = ctx.getTokens(); // 获取 token 流引用 + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 消耗起始关键字 "if" ts.expect("if"); @@ -120,6 +125,6 @@ public class IfStatementParser implements StatementParser { ts.expectType(TokenType.NEWLINE); // 构建并返回 IfNode,包含条件、then 分支和 else 分支 - return new IfNode(condition, thenBranch, elseBranch); + return new IfNode(condition, thenBranch, elseBranch, line, column, file); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java index 583b5c9..4422636 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java @@ -64,6 +64,12 @@ public class LoopStatementParser implements StatementParser { public LoopNode parse(ParserContext ctx) { TokenStream ts = ctx.getTokens(); + // 获取当前 token 的行号、列号 + int loop_line = ctx.getTokens().peek().getLine(); + int loop_column = ctx.getTokens().peek().getCol(); + + String file = ctx.getSourceName(); + // 匹配 loop: 起始语法 ParserUtils.matchHeader(ts, "loop"); @@ -101,12 +107,16 @@ public class LoopStatementParser implements StatementParser { sections.put("update", new FlexibleSectionParser.SectionDefinition( ts1 -> ts1.peek().getLexeme().equals("update"), (ctx1, ts1) -> { + // 获取当前 token 的行号、列号 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + ParserUtils.matchHeader(ts1, "update"); String varName = ts1.expectType(TokenType.IDENTIFIER).getLexeme(); ts1.expect("="); ExpressionNode expr = new PrattExpressionParser().parse(ctx1); ts1.expectType(TokenType.NEWLINE); - update[0] = new AssignmentNode(varName, expr); + update[0] = new AssignmentNode(varName, expr, line, column, file); ParserUtils.skipNewlines(ts1); } )); @@ -140,6 +150,6 @@ public class LoopStatementParser implements StatementParser { ParserUtils.matchFooter(ts, "loop"); // 返回构造完成的 LoopNode - return new LoopNode(initializer[0], condition[0], update[0], body); + return new LoopNode(initializer[0], condition[0], update[0], body, loop_line, loop_column, file); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java index 8a6a6a2..080f1e6 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java @@ -35,6 +35,11 @@ public class ReturnStatementParser implements StatementParser { */ @Override public ReturnNode parse(ParserContext ctx) { + // 获取当前 token 的行号、列号和文件名 + int line = ctx.getTokens().peek().getLine(); + int column = ctx.getTokens().peek().getCol(); + String file = ctx.getSourceName(); + // 消耗 "return" 关键字 ctx.getTokens().expect("return"); @@ -49,6 +54,6 @@ public class ReturnStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 构建并返回 ReturnNode(可能为空表达式) - return new ReturnNode(expr); + return new ReturnNode(expr, line, column, file); } } From 43fd1d175d90d2c0654cbbe5eba012c13dcac7e1 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Fri, 27 Jun 2025 13:14:52 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20=E5=8C=85=E5=90=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java b/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java index c76537b..4d8e9d1 100644 --- a/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java +++ b/src/main/java/org/jcnc/snow/pkg/tasks/CompileTask.java @@ -1,7 +1,7 @@ package org.jcnc.snow.pkg.tasks; import org.jcnc.snow.cli.commands.CompileCommand; -import org.jcnc.snow.compiler.backend.util.OpHelper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.backend.alloc.RegisterAllocator; import org.jcnc.snow.compiler.backend.builder.VMCodeGenerator; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; From 237c35f0a0032ed15e31aa8c883d318e3cab3485 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Fri, 27 Jun 2025 13:18:03 +0800 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=B5=8C=E5=A5=97=E6=A8=A1=E5=BC=8F=E6=95=B0=E4=B8=8D=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jcnc/snow/compiler/ir/builder/StatementBuilder.java | 9 ++++++--- .../analyzers/expression/CallExpressionAnalyzer.java | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java index 2290278..f731c57 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java @@ -66,12 +66,12 @@ public class StatementBuilder { buildIf(ifNode); return; } - if (stmt instanceof ExpressionStatementNode(ExpressionNode exp)) { + if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, _, _, _)) { // 纯表达式语句,如 foo(); expr.build(exp); return; } - if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs)) { + if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, _, _, _)) { // 赋值语句,如 a = b + 1; final String type = ctx.getScope().lookupType(var); @@ -208,7 +208,10 @@ public class StatementBuilder { if (cond instanceof BinaryExpressionNode( ExpressionNode left, String operator, - ExpressionNode right + ExpressionNode right, + _, + _, + _ ) && ComparisonUtils.isComparisonOperator(operator)) { 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 b82d78f..9a6f923 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 @@ -51,8 +51,8 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer