From f3f8a8de70bf41155851b6489631d0a6323833e4 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:23:54 +0800 Subject: [PATCH 01/62] refactor: OpHelper.java --- .../java/org/jcnc/snow/compiler/backend/utils/OpHelper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java index de873b8..8dc5529 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java @@ -135,7 +135,6 @@ public final class OpHelper { Map revmap = new HashMap<>(); // reverse map OPCODE_MAP.forEach((key, value) -> revmap.put(Integer.parseInt(value), key)); - OPCODE_NAME_MAP = Collections.unmodifiableMap(revmap); } @@ -197,7 +196,7 @@ public final class OpHelper { public static String opcodeName(int code) { String name = OPCODE_NAME_MAP.get(code); if (name == null) { - throw new IllegalStateException("Unknown opcode: " + name); + throw new IllegalStateException("Unknown opcode: " + code); } return name; } From 8340e2bacce510c15f51516ec1e5cce86e8b65e6 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:28:12 +0800 Subject: [PATCH 02/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20byte8=20?= =?UTF-8?q?=E8=BD=AC=20short16=E3=80=81long64=E3=80=81float32=E3=80=81doub?= =?UTF-8?q?le64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/B2DCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2FCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2LCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2SCommand.java | 47 +++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java new file mode 100644 index 0000000..1ca0655 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2DCommand Opcode: Represents the type conversion operation from byte8 to double64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2DCommand implements Command { + + /** + * Default constructor for creating an instance of B2DCommand. + */ + public B2DCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to double64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java new file mode 100644 index 0000000..c61891b --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2FCommand Opcode: Represents the type conversion operation from byte8 to float32 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a float32 value.
  4. + *
  5. Push the converted float32 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2FCommand implements Command { + + /** + * Default constructor for creating an instance of B2FCommand. + */ + public B2FCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to float32 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java new file mode 100644 index 0000000..344b49d --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2LCommand Opcode: Represents the type conversion operation from byte8 to long64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2LCommand implements Command { + + /** + * Default constructor for creating an instance of B2LCommand. + */ + public B2LCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to long64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java new file mode 100644 index 0000000..1f09ff9 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2SCommand Opcode: Represents the type conversion operation from byte8 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a short16 value.
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2SCommand implements Command { + + /** + * Default constructor for creating an instance of B2SCommand. + */ + public B2SCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + short convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 9d7d03e91cf7dee327948268e8c2139196dd64ea Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:31:16 +0800 Subject: [PATCH 03/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20short16=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81long64=E3=80=81float32=E3=80=81double?= =?UTF-8?q?64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/S2BCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2DCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2FCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2LCommand.java | 47 +++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java new file mode 100644 index 0000000..fa86e5f --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2BCommand Opcode: Represents the type conversion operation from short16 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to a byte8 value.
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to a byte8 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2BCommand implements Command { + + /** + * Default constructor for creating an instance of S2BCommand. + */ + public S2BCommand() { + // Empty constructor + } + + /** + * Executes the short16 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + byte convertedValue = (byte) ((short) operandStack.pop()); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java new file mode 100644 index 0000000..2f3381f --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2DCommand Opcode: Represents the type conversion operation from short16 to double64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to an double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to an double64 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2DCommand implements Command { + + /** + * Default constructor for creating an instance of S2DCommand. + */ + public S2DCommand() { + // Empty constructor + } + + /** + * Executes the short16 to double64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java new file mode 100644 index 0000000..78fbb4a --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2FCommand Opcode: Represents the type conversion operation from short16 to float32 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to an float32 value.
  4. + *
  5. Push the converted float32 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to an float32 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2FCommand implements Command { + + /** + * Default constructor for creating an instance of S2FCommand. + */ + public S2FCommand() { + // Empty constructor + } + + /** + * Executes the short16 to float32 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java new file mode 100644 index 0000000..cec58e6 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2LCommand Opcode: Represents the type conversion operation from short16 to long64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to a long64 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2LCommand implements Command { + + /** + * Default constructor for creating an instance of S2LCommand. + */ + public S2LCommand() { + // Empty constructor + } + + /** + * Executes the short16 to long64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} From ccc9e3e50f6f2942d045bb06a806b5a8613845dd Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:00:09 +0800 Subject: [PATCH 04/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20double64=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/D2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/D2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java new file mode 100644 index 0000000..7180d2e --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * D2BCommand Opcode: Represents the type conversion operation from double64 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top double64 value from the operand stack.
  2. + *
  3. Convert the double64 value to a byte8 value (this may involve truncation).
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to narrow a double64 value to a byte8 type for further integer-based operations.

+ */ +public class D2BCommand implements Command { + + /** + * Default constructor for creating an instance of D2BCommand. + */ + public D2BCommand() { + // Empty constructor + } + + /** + * Executes the double64 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double value = (double) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java new file mode 100644 index 0000000..ab11cf0 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * D2SCommand Opcode: Represents the type conversion operation from double64 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top double64 value from the operand stack.
  2. + *
  3. Convert the double64 value to an short16 value (this may involve truncation).
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to narrow a double64 value to an short16 type for further integer-based operations.

+ */ +public class D2SCommand implements Command { + + /** + * Default constructor for creating an instance of D2SCommand. + */ + public D2SCommand() { + // Empty constructor + } + + /** + * Executes the double64 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double value = (double) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From ec94191153e0ec2233548b824c7328e5e5b59caa Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:02:30 +0800 Subject: [PATCH 05/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20float32=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/F2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/F2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java new file mode 100644 index 0000000..5240f86 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * F2BCommand Opcode: Represents the type conversion operation from float32 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top float32 value from the operand stack.
  2. + *
  3. Convert the float32 value to a byte8 value (this may involve truncation).
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to convert a float32 value to a byte8 type for further integer operations or comparisons.

+ */ +public class F2BCommand implements Command { + + /** + * Default constructor for creating an instance of F2BCommand. + */ + public F2BCommand() { + // Empty constructor + } + + /** + * Executes the float32 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float value = (float) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java new file mode 100644 index 0000000..83a79b5 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * F2SCommand Opcode: Represents the type conversion operation from float32 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top float32 value from the operand stack.
  2. + *
  3. Convert the float32 value to a short16 value (this may involve truncation).
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to convert a float32 value to a short16 type for further integer operations or comparisons.

+ */ +public class F2SCommand implements Command { + + /** + * Default constructor for creating an instance of F2SCommand. + */ + public F2SCommand() { + // Empty constructor + } + + /** + * Executes the float32 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float value = (float) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From fe9a8e750550617484b133a2c36e705397c1af48 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:04:23 +0800 Subject: [PATCH 06/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20long64=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/L2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/L2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java new file mode 100644 index 0000000..cde429c --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * L2BCommand Opcode: Represents the type conversion operation from long64 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a byte8 value.
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a byte8 type for high-precision floating-point computations.

+ */ +public class L2BCommand implements Command { + + /** + * Default constructor for creating an instance of L2BCommand. + */ + public L2BCommand() { + // Empty constructor + } + + /** + * Executes the long64 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long value = (long) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java new file mode 100644 index 0000000..54652d6 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * L2SCommand Opcode: Represents the type conversion operation from long64 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a short16 value.
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a short16 type for high-precision floating-point computations.

+ */ +public class L2SCommand implements Command { + + /** + * Default constructor for creating an instance of L2SCommand. + */ + public L2SCommand() { + // Empty constructor + } + + /** + * Executes the long64 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long value = (long) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 3466c27c9e7ac081ff22b6b9bbe34876549305c0 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:07:07 +0800 Subject: [PATCH 07/62] =?UTF-8?q?docs:=20=E4=BF=AE=E6=94=B9=E6=8B=BC?= =?UTF-8?q?=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java | 4 ++-- .../org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java | 4 ++-- .../org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java index ab11cf0..41a8cec 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top double64 value from the operand stack.
  2. - *
  3. Convert the double64 value to an short16 value (this may involve truncation).
  4. + *
  5. Convert the double64 value to a short16 value (this may involve truncation).
  6. *
  7. Push the converted short16 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to narrow a double64 value to an short16 type for further integer-based operations.

+ *

This opcode is used to narrow a double64 value to a short16 type for further integer-based operations.

*/ public class D2SCommand implements Command { diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java index 2f3381f..7703f26 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an double64 value.
  4. + *
  5. Convert the short16 value to a double64 value.
  6. *
  7. Push the converted double64 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to widen a short16 value to an double64 type, facilitating subsequent integer arithmetic or comparison operations.

+ *

This opcode is used to widen a short16 value to a double64 type, facilitating subsequent integer arithmetic or comparison operations.

*/ public class S2DCommand implements Command { diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java index 78fbb4a..478e397 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an float32 value.
  4. + *
  5. Convert the short16 value to a float32 value.
  6. *
  7. Push the converted float32 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to widen a short16 value to an float32 type, facilitating subsequent integer arithmetic or comparison operations.

+ *

This opcode is used to widen a short16 value to a float32 type, facilitating subsequent integer arithmetic or comparison operations.

*/ public class S2FCommand implements Command { From eee77ea45183276bebadcb8ebff22afdf77939b9 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:08:49 +0800 Subject: [PATCH 08/62] =?UTF-8?q?style:=20=E7=BB=9F=E4=B8=80=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java index fa86e5f..d94eb8a 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java @@ -40,7 +40,8 @@ public class S2BCommand implements Command { @Override public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { - byte convertedValue = (byte) ((short) operandStack.pop()); + short value = (short) operandStack.pop(); + byte convertedValue = (byte) value; operandStack.push(convertedValue); return currentPC + 1; } From 840ac25e8a7d99ec22b650f4fc3fad90390457bb Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 8 Jul 2025 12:39:15 +0800 Subject: [PATCH 09/62] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20AST?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E4=B8=AD=E7=9A=84=E4=BD=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=A1=A8=E7=A4=BA=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 NodeContext 类统一表示节点的上下文信息(行号、列号、文件名) - 修改相关 AST 节点的构造函数,使用 NodeContext 替代单独的行号、列号和文件名参数 - 更新解析器代码,创建 NodeContext 实例以传递给 AST节点 - 此重构简化了 AST 节点的参数列表,提高了代码的可维护性和可读性 --- .../compiler/ir/builder/IRProgramBuilder.java | 5 +-- .../compiler/ir/builder/StatementBuilder.java | 9 ++-- .../compiler/ir/utils/ComparisonUtils.java | 3 +- .../compiler/ir/utils/ExpressionUtils.java | 3 +- .../compiler/parser/ast/AssignmentNode.java | 11 ++--- .../parser/ast/BinaryExpressionNode.java | 9 ++-- .../compiler/parser/ast/BoolLiteralNode.java | 18 ++++---- .../parser/ast/CallExpressionNode.java | 36 ++------------- .../compiler/parser/ast/DeclarationNode.java | 45 +++++-------------- .../parser/ast/ExpressionStatementNode.java | 11 ++--- .../compiler/parser/ast/FunctionNode.java | 11 ++--- .../compiler/parser/ast/IdentifierNode.java | 11 ++--- .../jcnc/snow/compiler/parser/ast/IfNode.java | 20 ++------- .../snow/compiler/parser/ast/ImportNode.java | 11 ++--- .../snow/compiler/parser/ast/LoopNode.java | 11 ++--- .../parser/ast/MemberExpressionNode.java | 15 +++---- .../snow/compiler/parser/ast/ModuleNode.java | 10 ++--- .../parser/ast/NumberLiteralNode.java | 9 ++-- .../compiler/parser/ast/ParameterNode.java | 15 +++---- .../snow/compiler/parser/ast/ReturnNode.java | 45 +++++-------------- .../parser/ast/StringLiteralNode.java | 11 ++--- .../parser/ast/UnaryExpressionNode.java | 9 ++-- .../snow/compiler/parser/ast/base/Node.java | 20 +-------- .../compiler/parser/ast/base/NodeContext.java | 11 +++++ .../expression/BinaryOperatorParselet.java | 8 ++-- .../expression/BoolLiteralParselet.java | 3 +- .../parser/expression/CallParselet.java | 4 +- .../parser/expression/IdentifierParselet.java | 3 +- .../parser/expression/MemberParselet.java | 3 +- .../expression/NumberLiteralParselet.java | 3 +- .../expression/StringLiteralParselet.java | 3 +- .../expression/UnaryOperatorParselet.java | 3 +- .../compiler/parser/function/ASTPrinter.java | 16 +++---- .../parser/function/FunctionParser.java | 5 ++- .../compiler/parser/module/ImportParser.java | 3 +- .../compiler/parser/module/ModuleParser.java | 3 +- .../statement/DeclarationStatementParser.java | 3 +- .../statement/ExpressionStatementParser.java | 5 ++- .../parser/statement/IfStatementParser.java | 3 +- .../parser/statement/LoopStatementParser.java | 5 ++- .../statement/ReturnStatementParser.java | 3 +- .../parser/utils/ASTJsonSerializer.java | 20 ++++----- .../expression/CallExpressionAnalyzer.java | 7 +-- .../semantic/error/SemanticError.java | 7 +-- 44 files changed, 177 insertions(+), 292 deletions(-) create mode 100644 src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java 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 5513fdc..225743e 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 @@ -5,6 +5,7 @@ import org.jcnc.snow.compiler.ir.core.IRProgram; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -81,9 +82,7 @@ public final class IRProgramBuilder { null, String.valueOf(List.of()), List.of(stmt), - -1, - -1, - "" + new NodeContext(-1, -1, "") ); } } 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 557634b..78e42fa 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 @@ -6,6 +6,7 @@ import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.Locale; @@ -66,12 +67,12 @@ public class StatementBuilder { buildIf(ifNode); return; } - if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, int _, int _, String _)) { + if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, NodeContext _)) { // 纯表达式语句,如 foo(); expr.build(exp); return; } - if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, int _, int _, String _)) { + if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, NodeContext _)) { // 赋值语句,如 a = b + 1; final String type = ctx.getScope().lookupType(var); @@ -209,9 +210,7 @@ public class StatementBuilder { ExpressionNode left, String operator, ExpressionNode right, - _, - _, - _ + NodeContext _ ) && ComparisonUtils.isComparisonOperator(operator)) { diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java index 08b42b8..70ac8f5 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.ir.core.IROpCode; import org.jcnc.snow.compiler.ir.core.IROpCodeMappings; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -41,7 +42,7 @@ public final class ComparisonUtils { /* ------------ 内部工具 ------------ */ private static boolean isLongLiteral(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { return value.endsWith("L") || value.endsWith("l"); } return false; // 变量暂不处理(后续可扩展符号表查询) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java index 291b861..2eed575 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java @@ -7,6 +7,7 @@ import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -127,7 +128,7 @@ public final class ExpressionUtils { /** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */ private static char typeChar(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { char last = Character.toLowerCase(value.charAt(value.length() - 1)); return switch (last) { case 'b','s','i','l','f','d' -> last; 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 eace610..34b387c 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。 @@ -16,16 +17,12 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; * * @param variable 左值变量名(即赋值目标) * @param value 表达式右值(即赋值来源) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号等) */ public record AssignmentNode( String variable, ExpressionNode value, - int line, - int column, - String file + NodeContext context ) implements StatementNode { /** @@ -40,4 +37,4 @@ public record AssignmentNode( public String toString() { return variable + " = " + value; } -} \ No newline at end of file +} 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 40412de..ec56cc2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code BinaryExpressionNode} 表示抽象语法树(AST)中的二元运算表达式节点。 @@ -12,17 +13,13 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * @param left 左操作数(子表达式) * @param operator 运算符字符串(如 "+", "-", "*", "/" 等) * @param right 右操作数(子表达式) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文(包含行号、列号等信息) */ public record BinaryExpressionNode( ExpressionNode left, String operator, ExpressionNode right, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java index bb46a30..909a43c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 表达布尔类型的字面量常量(如 "true" 或 "false")。 *

* - * @param value 字面量的布尔值 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param value 字面量的布尔值 + * @param context 节点上下文信息(行号、列号等) */ public record BoolLiteralNode( boolean value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -28,10 +25,11 @@ public record BoolLiteralNode( * 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。 *

* - * @param lexeme 布尔字面量的字符串表示 + * @param lexeme 布尔字面量的字符串表示 + * @param context 节点上下文信息(行号、列号等) */ - public BoolLiteralNode(String lexeme, int line, int column, String file) { - this(Boolean.parseBoolean(lexeme), line, column, file); + public BoolLiteralNode(String lexeme, NodeContext context) { + this(Boolean.parseBoolean(lexeme), context); } /** 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 d7dbce9..8033989 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -12,16 +13,12 @@ import java.util.List; * * @param callee 被调用的表达式节点,通常为函数标识符或成员访问表达式,表示函数名或方法名等。 * @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。 - * @param line 当前表达式所在的行号,方便调试和错误定位。 - * @param column 当前表达式所在的列号,用于精确定位错误位置。 - * @param file 当前表达式所在的文件,用于错误定位。 + * @param context 节点上下文信息(包含行号、列号等)。 */ public record CallExpressionNode( ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名 List arguments, // 函数调用的参数表达式列表 - int line, // 当前节点所在的行号 - int column, // 当前节点所在的列号 - String file // 当前节点所在的文件 + NodeContext context // 节点上下文信息(包含行号、列号等) ) implements ExpressionNode { /** @@ -43,31 +40,4 @@ public record CallExpressionNode( sb.append(")"); // 拼接右括号 return sb.toString(); // 返回拼接好的字符串 } - - /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 - */ - public int line() { - return line; - } - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - public int column() { - return column; - } - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - public String file() { - return file; - } } 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 9e1edf5..dd5bea6 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,14 +24,8 @@ public class DeclarationNode implements StatementNode { /** 可选的初始化表达式 */ private final Optional initializer; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code DeclarationNode} 实例。 @@ -38,14 +33,13 @@ public class DeclarationNode implements StatementNode { * @param name 变量名称 * @param type 变量类型字符串(如 "int"、"string") * @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化 + * @param context 节点上下文信息(包含行号、列号等) */ - public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) { + public DeclarationNode(String name, String type, ExpressionNode initializer, NodeContext context) { this.name = name; this.type = type; this.initializer = Optional.ofNullable(initializer); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -76,27 +70,12 @@ public class DeclarationNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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 1a2f7a5..9b1d821 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。 @@ -11,14 +12,10 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; *

* * @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ExpressionStatementNode( ExpressionNode expression, - int line, - int column, - String file + NodeContext context ) 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 29ab884..d1b29f2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义 * @param returnType 函数的返回类型(如 "int"、"void" 等) * @param body 函数体语句块,由一组 {@link StatementNode} 构成 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record FunctionNode( String name, List parameters, String returnType, List body, - int line, - int column, - String file + NodeContext context ) 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 de0ed17..eb46091 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code IdentifierNode} 表示抽象语法树(AST)中的标识符表达式节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 在语义分析中,通常需要将此类节点绑定到其声明位置或符号表项。 *

* - * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") + * @param context 节点上下文信息(包含行号、列号等) */ public record IdentifierNode( String name, - int line, - int column, - String file + NodeContext context ) 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 a26c8e2..ecc0dd1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -16,29 +17,16 @@ import java.util.List; * 若 condition 为假,则执行 else 分支(如果提供)。 *

*

- * 示例语法结构: - *

- *
{@code
- * if (x > 0) {
- *     print("Positive");
- * } else {
- *     print("Negative");
- * }
- * }
* * @param condition 控制分支执行的条件表达式 * @param thenBranch 条件为 true 时执行的语句块 * @param elseBranch 条件为 false 时执行的语句块(可为空) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record IfNode( ExpressionNode condition, List thenBranch, List elseBranch, - int line, - int column, - String file + NodeContext context ) 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 c6b65e9..a45c751 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。 @@ -14,14 +15,10 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; *

* * @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ImportNode( String moduleName, - int line, - int column, - String file + NodeContext context ) 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 a8ddbe1..2ba283e 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param condition 每次迭代前评估的条件表达式,控制循环是否继续 * @param update 每轮迭代完成后执行的更新语句 * @param body 循环体语句列表,表示循环主体执行逻辑 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号、文件名等) */ public record LoopNode( StatementNode initializer, ExpressionNode condition, StatementNode update, List body, - int line, - int column, - String file + NodeContext context ) 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 d0ac38e..8ab233b 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code MemberExpressionNode} 表示抽象语法树(AST)中的成员访问表达式节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。 *

* - * @param object 左侧对象表达式,表示成员所属的作用域或容器 - * @param member 要访问的成员名称(字段名或方法名) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param object 左侧对象表达式,表示成员所属的作用域或容器 + * @param member 要访问的成员名称(字段名或方法名) + * @param context 节点上下文信息(包含行号、列号等) */ public record MemberExpressionNode( ExpressionNode object, String member, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -35,4 +32,4 @@ public record MemberExpressionNode( public String toString() { return object + "." + member; } -} \ No newline at end of file +} 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 05d47de..84262dd 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; import java.util.StringJoiner; @@ -8,22 +9,17 @@ import java.util.StringJoiner; /** * 表示模块定义的 AST 节点。 * 一个模块通常由模块名、导入语句列表和函数定义列表组成。 - * } * * @param name 模块名称。 * @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。 * @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ModuleNode( String name, List imports, List functions, - int line, - int column, - String file + NodeContext context ) implements Node { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java index 9f253e2..6806112 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code NumberLiteralNode} 表示抽象语法树(AST)中的数字字面量表达式节点。 @@ -11,15 +12,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 数字字面量的原始字符串表示 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record NumberLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** 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 0fbdc18..593d46f 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ParameterNode} 表示抽象语法树(AST)中的函数参数定义节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; * 用于构成函数签名并参与类型检查与函数调用匹配。 *

* - * @param name 参数名称标识符 - * @param type 参数类型字符串(如 "int"、"string") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 参数名称标识符 + * @param type 参数类型字符串(如 "int"、"string") + * @param context 节点上下文信息(包含行号、列号等) */ public record ParameterNode( String name, String type, - int line, - int column, - String file + NodeContext context ) implements Node { /** @@ -35,4 +32,4 @@ public record ParameterNode( public String toString() { return name + ":" + type; } -} \ No newline at end of file +} 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 0fc2254..b6d17e1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,25 +24,18 @@ public class ReturnNode implements StatementNode { /** 可选的返回值表达式 */ private final Optional expression; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code ReturnNode} 实例。 * * @param expression 返回值表达式,如果无返回值则可为 {@code null} + * @param context 节点上下文信息(包含行号、列号等) */ - public ReturnNode(ExpressionNode expression, int line, int column, String file) { + public ReturnNode(ExpressionNode expression, NodeContext context) { this.expression = Optional.ofNullable(expression); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -54,27 +48,12 @@ public class ReturnNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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/StringLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java index daa9f42..dd0e61f 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code StringLiteralNode} 表示抽象语法树(AST)中的字符串字面量表达式节点。 @@ -10,15 +11,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 字符串常量的内容,原始值中不包含双引号 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record StringLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -33,4 +30,4 @@ public record StringLiteralNode( public String toString() { return "\"" + value + "\""; } -} \ 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 7e38ebc..cc22e6a 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。 @@ -15,16 +16,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * * @param operator 一元运算符(仅 "-" 或 "!") * @param operand 运算对象 / 右操作数 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record UnaryExpressionNode( String operator, ExpressionNode operand, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java index 5cba805..8b1e906 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java @@ -17,23 +17,7 @@ package org.jcnc.snow.compiler.parser.ast.base; */ public interface Node { /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 + * 获取节点的上下文(行/列/文件等信息)。 */ - int line(); - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - int column(); - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - String file(); + NodeContext context(); } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java new file mode 100644 index 0000000..e73ce21 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java @@ -0,0 +1,11 @@ +package org.jcnc.snow.compiler.parser.ast.base; + +/** + * NodeContext 记录 AST 节点的位置信息(文件、行、列)。 + */ +public record NodeContext(int line, int column, String file) { + @Override + public String toString() { + return file + ":" + line + ":" + column; + } +} 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 adee8bd..973b81a 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -46,12 +47,9 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i int prec = precedence.ordinal(); // 右侧表达式根据结合性确定优先级绑定 - ExpressionNode right = new PrattExpressionParser().parseExpression( - ctx, - leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1] - ); + ExpressionNode right = new PrattExpressionParser().parseExpression(ctx, leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]); - return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file); + return new BinaryExpressionNode(left, op.getLexeme(), right, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java index cfd49db..677896d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -28,6 +29,6 @@ public class BoolLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new BoolLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new BoolLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } 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 9f5478a..6fd7f4a 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.parser.ast.CallExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -45,7 +46,8 @@ public class CallParselet implements InfixParselet { ctx.getTokens().expect(")"); // 消费并验证 ")" // 创建 CallExpressionNode 并传递位置信息 - return new CallExpressionNode(left, args, line, column, file); + return new CallExpressionNode(left, args, new NodeContext(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 7e46337..f0b9a34 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.IdentifierNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -29,6 +30,6 @@ public class IdentifierParselet implements PrefixParselet { int column = ctx.getTokens().peek(-1).getCol(); String file = ctx.getSourceName(); - return new IdentifierNode(token.getLexeme(), line, column, file); + return new IdentifierNode(token.getLexeme(), new NodeContext(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 ed3cd58..76f1c7f 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -34,7 +35,7 @@ public class MemberParselet implements InfixParselet { String file = ctx.getSourceName(); String member = ts.expectType(TokenType.IDENTIFIER).getLexeme(); - return new MemberExpressionNode(left, member, line, column, file); + return new MemberExpressionNode(left, member, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java index 4b75174..69ac8d7 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -24,6 +25,6 @@ public class NumberLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new NumberLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new NumberLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java index b4eb3b3..542a097 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.StringLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -27,6 +28,6 @@ public class StringLiteralParselet implements PrefixParselet { public ExpressionNode parse(ParserContext ctx, Token token) { String raw = token.getRaw(); String content = raw.substring(1, raw.length() - 1); - return new StringLiteralNode(content, token.getLine(), token.getCol(), ctx.getSourceName()); + return new StringLiteralNode(content, new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of 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 5aedf93..113ab94 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -55,6 +56,6 @@ public class UnaryOperatorParselet implements PrefixParselet { /* ------------------------------------------------------------ * 2. 封装成 AST 节点并返回。 * ------------------------------------------------------------ */ - return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file); + return new UnaryExpressionNode(token.getLexeme(), operand, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java index 75ffbca..c12edb3 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.utils.ASTJsonSerializer; import org.jcnc.snow.compiler.parser.utils.JsonFormatter; @@ -66,8 +67,8 @@ public class ASTPrinter { } } case FunctionNode( - String name, List parameters, String returnType, List body - , int _, int _, String _ + String name, List parameters, String returnType, List body, + NodeContext _ ) -> { System.out.println(pad + "function " + name + "(params=" + parameters + ", return=" + returnType + ")"); @@ -82,11 +83,10 @@ public class ASTPrinter { .orElse(""); System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init); } - case AssignmentNode(String variable, ExpressionNode value, int _, int _, String _) -> + case AssignmentNode(String variable, ExpressionNode value, NodeContext _) -> System.out.println(pad + variable + " = " + value); case IfNode( - ExpressionNode condition, List thenBranch, List elseBranch, int _, - int _, String _ + ExpressionNode condition, List thenBranch, List elseBranch, NodeContext _ ) -> { System.out.println(pad + "if " + condition); for (StatementNode stmt : thenBranch) { @@ -100,8 +100,8 @@ public class ASTPrinter { } } case LoopNode( - StatementNode initializer, ExpressionNode condition, StatementNode update, List body - , int _, int _, String _ + StatementNode initializer, ExpressionNode condition, StatementNode update, List body, + NodeContext _ ) -> { System.out.println(pad + "loop {"); print(initializer, indent + 1); @@ -116,7 +116,7 @@ public class ASTPrinter { } case ReturnNode r -> System.out.println(pad + "return" + r.getExpression().map(e -> " " + e).orElse("")); - case ExpressionStatementNode(ExpressionNode expression, int _, int _, String _) -> + case ExpressionStatementNode(ExpressionNode expression, NodeContext _) -> System.out.println(pad + expression); case null, default -> System.out.println(pad + n); // 回退处理 } 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 a7a3449..3927767 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ParameterNode; @@ -74,7 +75,7 @@ public class FunctionParser implements TopLevelParser { parseFunctionFooter(ts); - return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file); + return new FunctionNode(functionName, parameters, returnType[0], body, new NodeContext(line, column, file)); } /** @@ -194,7 +195,7 @@ public class FunctionParser implements TopLevelParser { String ptype = ts.expectType(TokenType.TYPE).getLexeme(); skipComments(ts); ts.expectType(TokenType.NEWLINE); - list.add(new ParameterNode(pname, ptype, line, column, file)); + list.add(new ParameterNode(pname, ptype, new NodeContext(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 d5443ac..10ca4d5 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.module; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.ast.ImportNode; @@ -57,7 +58,7 @@ public class ImportParser { .getLexeme(); // 创建 ImportNode 节点并加入列表 - imports.add(new ImportNode(mod, line, column, file)); + imports.add(new ImportNode(mod, new NodeContext(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 8a21e70..fc8ff02 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ImportNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -93,6 +94,6 @@ public class ModuleParser implements TopLevelParser { ts.expect("end"); ts.expect("module"); - return new ModuleNode(name, imports, functions, line, column, file); + return new ModuleNode(name, imports, functions, new NodeContext(line, column, 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 2323ada..a7e6fa3 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.DeclarationNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -74,6 +75,6 @@ public class DeclarationStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 返回构建好的声明语法树节点 - return new DeclarationNode(name, type, init, line, column, file); + return new DeclarationNode(name, type, init, new NodeContext(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 f824b6b..36af619 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -56,12 +57,12 @@ public class ExpressionStatementParser implements StatementParser { ts.expect("="); ExpressionNode value = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new AssignmentNode(varName, value, line, column, file); + return new AssignmentNode(varName, value, new NodeContext(line, column, file)); } // 普通表达式语句 ExpressionNode expr = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new ExpressionStatementNode(expr, line, column, file); + return new ExpressionStatementNode(expr, new NodeContext(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 eda8bb1..24d6556 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.IfNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -125,6 +126,6 @@ public class IfStatementParser implements StatementParser { ts.expectType(TokenType.NEWLINE); // 构建并返回 IfNode,包含条件、then 分支和 else 分支 - return new IfNode(condition, thenBranch, elseBranch, line, column, file); + return new IfNode(condition, thenBranch, elseBranch, new NodeContext(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 4422636..c1a9c66 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.LoopNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -116,7 +117,7 @@ public class LoopStatementParser implements StatementParser { ts1.expect("="); ExpressionNode expr = new PrattExpressionParser().parse(ctx1); ts1.expectType(TokenType.NEWLINE); - update[0] = new AssignmentNode(varName, expr, line, column, file); + update[0] = new AssignmentNode(varName, expr, new NodeContext(line, column, file)); ParserUtils.skipNewlines(ts1); } )); @@ -150,6 +151,6 @@ public class LoopStatementParser implements StatementParser { ParserUtils.matchFooter(ts, "loop"); // 返回构造完成的 LoopNode - return new LoopNode(initializer[0], condition[0], update[0], body, loop_line, loop_column, file); + return new LoopNode(initializer[0], condition[0], update[0], body, new NodeContext(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 080f1e6..3b4c6c1 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.ReturnNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -54,6 +55,6 @@ public class ReturnStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 构建并返回 ReturnNode(可能为空表达式) - return new ReturnNode(expr, line, column, file); + return new ReturnNode(expr, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java index 231d9af..278a42c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.utils; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.*; @@ -82,8 +83,7 @@ public class ASTJsonSerializer { return switch (n) { // 模块节点 case ModuleNode( - String name, List imports, List functions, _, int _, - String _ + String name, List imports, List functions, NodeContext _ ) -> { Map map = newNodeMap("Module"); map.put("name", name); @@ -181,34 +181,34 @@ public class ASTJsonSerializer { return switch (expr) { // 二元表达式 case BinaryExpressionNode( - ExpressionNode left, String operator, ExpressionNode right, int _, int _, String _ + ExpressionNode left, String operator, ExpressionNode right, NodeContext _ ) -> exprMap("BinaryExpression", "left", exprToMap(left), "operator", operator, "right", exprToMap(right) ); // 一元表达式 - case UnaryExpressionNode(String operator, ExpressionNode operand, int _, int _, String _) -> + case UnaryExpressionNode(String operator, ExpressionNode operand, NodeContext _) -> exprMap("UnaryExpression", "operator", operator, "operand", exprToMap(operand) ); // 布尔字面量 - case BoolLiteralNode(boolean value, int _, int _, String _) -> exprMap("BoolLiteral", "value", value); + case BoolLiteralNode(boolean value, NodeContext _) -> exprMap("BoolLiteral", "value", value); // 标识符 - case IdentifierNode(String name, int _, int _, String _) -> exprMap("Identifier", "name", name); + case IdentifierNode(String name, NodeContext _) -> exprMap("Identifier", "name", name); // 数字字面量 - case NumberLiteralNode(String value, int _, int _, String _) -> exprMap("NumberLiteral", "value", value); + case NumberLiteralNode(String value, NodeContext _) -> exprMap("NumberLiteral", "value", value); // 字符串字面量 - case StringLiteralNode(String value, int _, int _, String _) -> exprMap("StringLiteral", "value", value); + case StringLiteralNode(String value, NodeContext _) -> exprMap("StringLiteral", "value", value); // 调用表达式 - case CallExpressionNode(ExpressionNode callee, List arguments, int _, int _, String _) -> { + case CallExpressionNode(ExpressionNode callee, List arguments, NodeContext _) -> { List args = new ArrayList<>(arguments.size()); for (ExpressionNode arg : arguments) args.add(exprToMap(arg)); yield exprMap("CallExpression", "callee", exprToMap(callee), "arguments", args); } // 成员访问表达式 - case MemberExpressionNode(ExpressionNode object, String member, int _, int _, String _) -> + case MemberExpressionNode(ExpressionNode object, String member, NodeContext _) -> exprMap("MemberExpression", "object", exprToMap(object), "member", member 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 83c331c..360ec99 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.semantic.analyzers.expression; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer; import org.jcnc.snow.compiler.semantic.core.Context; import org.jcnc.snow.compiler.semantic.core.ModuleInfo; @@ -51,8 +52,8 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer= 0 && col >= 0) ? "行 " + line + ", 列 " + col : "未知位置"); From fabde0026f79d5a8d88e11fbad1a119b2994e5f3 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Tue, 8 Jul 2025 20:19:45 +0800 Subject: [PATCH 10/62] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E6=95=B0=E5=80=BC=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/engine/VMOpCode.java | 200 ++++++++++-------- .../snow/vm/factories/CommandFactory.java | 29 ++- 2 files changed, 135 insertions(+), 94 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 c53f511..8b634ca 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java @@ -2043,34 +2043,33 @@ public class VMOpCode { // endregion // region Type Conversion (0x00C0-0x00DF) - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a long64 value.
  4. - *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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

- */ - public static final int I2L = 0x00C0; - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a short16 value (this may involve truncation).
  4. - *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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 = 0x00C1; + // region Byte8 (0x00C0-0xC4) + + public static final int B2S = 0x00C0; + + public static final int B2I = 0x00C1; + + public static final int B2L = 0x00C2; + + public static final int B2F = 0x00C3; + + public static final int B2D = 0x00C4; + // endregion Byte8 + + // region Short16 (0x00C5-0xC9) + + public static final int S2B = 0x00C5; + + public static final int S2I = 0x00C6; + + public static final int S2L = 0x00C7; + + public static final int S2F = 0x00C8; + + public static final int S2D = 0x00C9; + // endregion Short16 + + // region Int32 (0x00CA-0xCE) /** * I2B Opcode: Represents the type conversion operation from int32 to byte8 in the virtual machine. *

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

@@ -2084,21 +2083,37 @@ 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 = 0x00C2; + public static final int I2B = 0x00CA; + /** - * 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.

+ * 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.

* *

Execution Steps:

*
    *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a double64 value.
  4. - *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
  7. Convert the int32 value to a short16 value (this may involve truncation).
  8. + *
  9. Push the converted short16 value back onto the operand stack for subsequent operations.
  10. *
* - *

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

+ *

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 I2D = 0x00C3; + public static final int I2S = 0x00CB; + + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top int32 value from the operand stack.
  2. + *
  3. Convert the int32 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ + public static final int I2L = 0x00CC; /** * 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.

@@ -2112,7 +2127,29 @@ 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 = 0x00C4; + public static final int I2F = 0x00CD; + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top int32 value from the operand stack.
  2. + *
  3. Convert the int32 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ + public static final int I2D = 0x00CE; + // endregion Int32 + + // region Long64 (0x00CF-0xD3) + + public static final int L2B = 0x00CF; + + public static final int L2S = 0x00D0; + /** * 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.

@@ -2126,21 +2163,7 @@ 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 = 0x00C5; - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top long64 value from the operand stack.
  2. - *
  3. Convert the long64 value to a double64 value.
  4. - *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.

- */ - public static final int L2D = 0x00C6; + public static final int L2I = 0x00D1; /** * L2F Opcode: Represents the type conversion operation from long64 to float32 in the virtual machine. *

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

@@ -2154,7 +2177,29 @@ public class VMOpCode { * *

This opcode is used to convert a long64 value to a float32 type, typically for floating-point arithmetic involving long values.

*/ - public static final int L2F = 0x00C7; + public static final int L2F = 0x00D2; + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.

+ */ + public static final int L2D = 0x00D3; + // endregion Long64 + + // region Float32 (0x00D4-0xD8) + + public static final int F2B = 0x00D4; + + public static final int F2S = 0x00D5; + /** * F2I Opcode: Represents the type conversion operation from float32 to int32 in the virtual machine. *

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

@@ -2168,7 +2213,7 @@ public class VMOpCode { * *

This opcode is used to convert a float32 value to an int32 type for further integer-based operations or comparisons.

*/ - public static final int F2I = 0x00C8; + public static final int F2I = 0x00D6; /** * F2L Opcode: Represents the type conversion operation from float32 to long64 in the virtual machine. *

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

@@ -2182,7 +2227,7 @@ public class VMOpCode { * *

This opcode is used to widen a float32 value to a long64 type, which is useful when operations require a larger numeric range.

*/ - public static final int F2L = 0x00C9; + public static final int F2L = 0x00D7; /** * F2D Opcode: Represents the type conversion operation from float32 to double64 in the virtual machine. *

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

@@ -2196,7 +2241,15 @@ public class VMOpCode { * *

This opcode is used to promote a float32 value to a double64 type, thereby increasing precision for floating-point computations.

*/ - public static final int F2D = 0x00CA; + public static final int F2D = 0x00D8; + // endregion Float32 + + // region Double64 (0x00D9-0xDD) + + public static final int D2B = 0x00D9; + + public static final int D2S = 0x00DA; + /** * D2I Opcode: Represents the type conversion operation from double64 to int32 in the virtual machine. *

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

@@ -2210,7 +2263,7 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to an int32 type for further integer-based processing.

*/ - public static final int D2I = 0x00CB; + public static final int D2I = 0x00DB; /** * D2L Opcode: Represents the type conversion operation from double64 to long64 in the virtual machine. *

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

@@ -2224,7 +2277,7 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to a long64 type, which can then be used for integer operations.

*/ - public static final int D2L = 0x00CC; + public static final int D2L = 0x00DC; /** * D2F Opcode: Represents the type conversion operation from double64 to float32 in the virtual machine. *

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

@@ -2238,36 +2291,9 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to a float32 type when lower precision floating-point arithmetic is acceptable.

*/ - public static final int D2F = 0x00CD; - /** - * S2I Opcode: Represents the type conversion operation from short16 to int32 in the virtual machine. - *

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

- * - *

Execution Steps:

- *
    - *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an int32 value.
  4. - *
  5. Push the converted int32 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

This opcode is used to widen a short16 value to an int32 type, facilitating subsequent integer arithmetic or comparison operations.

- */ - public static final int S2I = 0x00CE; - /** - * B2I Opcode: Represents the type conversion operation from byte8 to int32 in the virtual machine. - *

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

- * - *

Execution Steps:

- *
    - *
  1. Pop the top byte8 value from the operand stack.
  2. - *
  3. Convert the byte8 value to an int32 value.
  4. - *
  5. Push the converted int32 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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 = 0x00CF; - // endregion + public static final int D2F = 0x00DD; + // endregion Double64 + // endregion Conversion // region Stack Control (0x0100-0x01FF) /** diff --git a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java index a5af00b..4054a11 100644 --- a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java +++ b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java @@ -207,26 +207,41 @@ public class CommandFactory { // endregion // region Type Conversion (0x00C0-0x00DF) - COMMANDS[VMOpCode.I2L] = new I2LCommand(); - COMMANDS[VMOpCode.I2S] = new I2SCommand(); + COMMANDS[VMOpCode.B2S] = new B2SCommand(); + COMMANDS[VMOpCode.B2I] = new B2ICommand(); + COMMANDS[VMOpCode.B2L] = new B2LCommand(); + COMMANDS[VMOpCode.B2F] = new B2FCommand(); + COMMANDS[VMOpCode.B2D] = new B2DCommand(); + + COMMANDS[VMOpCode.S2B] = new S2BCommand(); + COMMANDS[VMOpCode.S2I] = new S2ICommand(); + COMMANDS[VMOpCode.S2L] = new S2LCommand(); + COMMANDS[VMOpCode.S2F] = new S2FCommand(); + COMMANDS[VMOpCode.S2D] = new S2DCommand(); + COMMANDS[VMOpCode.I2B] = new I2BCommand(); - COMMANDS[VMOpCode.I2D] = new I2DCommand(); + COMMANDS[VMOpCode.I2S] = new I2SCommand(); + COMMANDS[VMOpCode.I2L] = new I2LCommand(); COMMANDS[VMOpCode.I2F] = new I2FCommand(); + COMMANDS[VMOpCode.I2D] = new I2DCommand(); + COMMANDS[VMOpCode.L2B] = new L2BCommand(); + COMMANDS[VMOpCode.L2S] = new L2SCommand(); COMMANDS[VMOpCode.L2I] = new L2ICommand(); - COMMANDS[VMOpCode.L2D] = new L2DCommand(); COMMANDS[VMOpCode.L2F] = new L2FCommand(); + COMMANDS[VMOpCode.L2D] = new L2DCommand(); + COMMANDS[VMOpCode.F2B] = new F2BCommand(); + COMMANDS[VMOpCode.F2S] = new F2SCommand(); COMMANDS[VMOpCode.F2I] = new F2ICommand(); COMMANDS[VMOpCode.F2L] = new F2LCommand(); COMMANDS[VMOpCode.F2D] = new F2DCommand(); + COMMANDS[VMOpCode.D2B] = new D2BCommand(); + COMMANDS[VMOpCode.D2S] = new D2SCommand(); COMMANDS[VMOpCode.D2I] = new D2ICommand(); COMMANDS[VMOpCode.D2L] = new D2LCommand(); COMMANDS[VMOpCode.D2F] = new D2FCommand(); - - COMMANDS[VMOpCode.S2I] = new S2ICommand(); - COMMANDS[VMOpCode.B2I] = new B2ICommand(); // endregion // region Stack Control (0x0100-0x01FF) From f4d96cfa535f5a7f3740547e07856ab557288b76 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 9 Jul 2025 23:58:46 +0800 Subject: [PATCH 11/62] =?UTF-8?q?fix:=20=E5=9C=A8=E9=9D=9E=20void=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E4=B8=AD=E5=BC=BA=E5=88=B6=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20return=20=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 FunctionChecker 中添加一个检查,以确保具有非 void 返回类型的功能 类型必须至少包含一个返回节点。否则将引发语义错误。 --- .../compiler/semantic/core/FunctionChecker.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java index e6d69c3..66385b6 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java @@ -2,11 +2,13 @@ package org.jcnc.snow.compiler.semantic.core; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.ReturnNode; import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer; import org.jcnc.snow.compiler.semantic.error.SemanticError; import org.jcnc.snow.compiler.semantic.symbol.Symbol; import org.jcnc.snow.compiler.semantic.symbol.SymbolKind; import org.jcnc.snow.compiler.semantic.symbol.SymbolTable; +import org.jcnc.snow.compiler.semantic.type.BuiltinType; /** * {@code FunctionChecker} 是语义分析阶段中用于检查函数体语句合法性的调度器。 @@ -79,6 +81,19 @@ public record FunctionChecker(Context ctx) { )); } } + + // 检查非 void 函数是否至少包含一条 return 语句 + var returnType = ctx.parseType(fn.returnType()); + if (returnType != BuiltinType.VOID) { + boolean hasReturn = fn.body().stream() + .anyMatch(stmtNode -> stmtNode instanceof ReturnNode); + if (!hasReturn) { + ctx.errors().add(new SemanticError( + fn, + "非 void 函数必须包含至少一条 return 语句" + )); + } + } } } } From aefa9e2dff4476629d2a8f95dbac173f96a9add8 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 8 Jul 2025 12:39:15 +0800 Subject: [PATCH 12/62] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20AST?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E4=B8=AD=E7=9A=84=E4=BD=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=A1=A8=E7=A4=BA=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 NodeContext 类统一表示节点的上下文信息(行号、列号、文件名) - 修改相关 AST 节点的构造函数,使用 NodeContext 替代单独的行号、列号和文件名参数 - 更新解析器代码,创建 NodeContext 实例以传递给 AST节点 - 此重构简化了 AST 节点的参数列表,提高了代码的可维护性和可读性 --- .../compiler/ir/builder/IRProgramBuilder.java | 5 +-- .../compiler/ir/builder/StatementBuilder.java | 9 ++-- .../compiler/ir/utils/ComparisonUtils.java | 3 +- .../compiler/ir/utils/ExpressionUtils.java | 3 +- .../compiler/parser/ast/AssignmentNode.java | 11 ++--- .../parser/ast/BinaryExpressionNode.java | 9 ++-- .../compiler/parser/ast/BoolLiteralNode.java | 18 ++++---- .../parser/ast/CallExpressionNode.java | 36 ++------------- .../compiler/parser/ast/DeclarationNode.java | 45 +++++-------------- .../parser/ast/ExpressionStatementNode.java | 11 ++--- .../compiler/parser/ast/FunctionNode.java | 11 ++--- .../compiler/parser/ast/IdentifierNode.java | 11 ++--- .../jcnc/snow/compiler/parser/ast/IfNode.java | 20 ++------- .../snow/compiler/parser/ast/ImportNode.java | 11 ++--- .../snow/compiler/parser/ast/LoopNode.java | 11 ++--- .../parser/ast/MemberExpressionNode.java | 15 +++---- .../snow/compiler/parser/ast/ModuleNode.java | 10 ++--- .../parser/ast/NumberLiteralNode.java | 9 ++-- .../compiler/parser/ast/ParameterNode.java | 15 +++---- .../snow/compiler/parser/ast/ReturnNode.java | 45 +++++-------------- .../parser/ast/StringLiteralNode.java | 11 ++--- .../parser/ast/UnaryExpressionNode.java | 9 ++-- .../snow/compiler/parser/ast/base/Node.java | 20 +-------- .../compiler/parser/ast/base/NodeContext.java | 11 +++++ .../expression/BinaryOperatorParselet.java | 8 ++-- .../expression/BoolLiteralParselet.java | 3 +- .../parser/expression/CallParselet.java | 4 +- .../parser/expression/IdentifierParselet.java | 3 +- .../parser/expression/MemberParselet.java | 3 +- .../expression/NumberLiteralParselet.java | 3 +- .../expression/StringLiteralParselet.java | 3 +- .../expression/UnaryOperatorParselet.java | 3 +- .../compiler/parser/function/ASTPrinter.java | 16 +++---- .../parser/function/FunctionParser.java | 5 ++- .../compiler/parser/module/ImportParser.java | 3 +- .../compiler/parser/module/ModuleParser.java | 3 +- .../statement/DeclarationStatementParser.java | 3 +- .../statement/ExpressionStatementParser.java | 5 ++- .../parser/statement/IfStatementParser.java | 3 +- .../parser/statement/LoopStatementParser.java | 5 ++- .../statement/ReturnStatementParser.java | 3 +- .../parser/utils/ASTJsonSerializer.java | 20 ++++----- .../expression/CallExpressionAnalyzer.java | 7 +-- .../semantic/error/SemanticError.java | 7 +-- 44 files changed, 177 insertions(+), 292 deletions(-) create mode 100644 src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java 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 5513fdc..225743e 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 @@ -5,6 +5,7 @@ import org.jcnc.snow.compiler.ir.core.IRProgram; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -81,9 +82,7 @@ public final class IRProgramBuilder { null, String.valueOf(List.of()), List.of(stmt), - -1, - -1, - "" + new NodeContext(-1, -1, "") ); } } 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 557634b..78e42fa 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 @@ -6,6 +6,7 @@ import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.Locale; @@ -66,12 +67,12 @@ public class StatementBuilder { buildIf(ifNode); return; } - if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, int _, int _, String _)) { + if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, NodeContext _)) { // 纯表达式语句,如 foo(); expr.build(exp); return; } - if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, int _, int _, String _)) { + if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, NodeContext _)) { // 赋值语句,如 a = b + 1; final String type = ctx.getScope().lookupType(var); @@ -209,9 +210,7 @@ public class StatementBuilder { ExpressionNode left, String operator, ExpressionNode right, - _, - _, - _ + NodeContext _ ) && ComparisonUtils.isComparisonOperator(operator)) { diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java index 08b42b8..70ac8f5 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.ir.core.IROpCode; import org.jcnc.snow.compiler.ir.core.IROpCodeMappings; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -41,7 +42,7 @@ public final class ComparisonUtils { /* ------------ 内部工具 ------------ */ private static boolean isLongLiteral(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { return value.endsWith("L") || value.endsWith("l"); } return false; // 变量暂不处理(后续可扩展符号表查询) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java index 291b861..2eed575 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java @@ -7,6 +7,7 @@ import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -127,7 +128,7 @@ public final class ExpressionUtils { /** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */ private static char typeChar(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { char last = Character.toLowerCase(value.charAt(value.length() - 1)); return switch (last) { case 'b','s','i','l','f','d' -> last; 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 eace610..34b387c 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。 @@ -16,16 +17,12 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; * * @param variable 左值变量名(即赋值目标) * @param value 表达式右值(即赋值来源) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号等) */ public record AssignmentNode( String variable, ExpressionNode value, - int line, - int column, - String file + NodeContext context ) implements StatementNode { /** @@ -40,4 +37,4 @@ public record AssignmentNode( public String toString() { return variable + " = " + value; } -} \ No newline at end of file +} 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 40412de..ec56cc2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code BinaryExpressionNode} 表示抽象语法树(AST)中的二元运算表达式节点。 @@ -12,17 +13,13 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * @param left 左操作数(子表达式) * @param operator 运算符字符串(如 "+", "-", "*", "/" 等) * @param right 右操作数(子表达式) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文(包含行号、列号等信息) */ public record BinaryExpressionNode( ExpressionNode left, String operator, ExpressionNode right, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java index bb46a30..909a43c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 表达布尔类型的字面量常量(如 "true" 或 "false")。 *

* - * @param value 字面量的布尔值 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param value 字面量的布尔值 + * @param context 节点上下文信息(行号、列号等) */ public record BoolLiteralNode( boolean value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -28,10 +25,11 @@ public record BoolLiteralNode( * 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。 *

* - * @param lexeme 布尔字面量的字符串表示 + * @param lexeme 布尔字面量的字符串表示 + * @param context 节点上下文信息(行号、列号等) */ - public BoolLiteralNode(String lexeme, int line, int column, String file) { - this(Boolean.parseBoolean(lexeme), line, column, file); + public BoolLiteralNode(String lexeme, NodeContext context) { + this(Boolean.parseBoolean(lexeme), context); } /** 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 d7dbce9..8033989 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -12,16 +13,12 @@ import java.util.List; * * @param callee 被调用的表达式节点,通常为函数标识符或成员访问表达式,表示函数名或方法名等。 * @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。 - * @param line 当前表达式所在的行号,方便调试和错误定位。 - * @param column 当前表达式所在的列号,用于精确定位错误位置。 - * @param file 当前表达式所在的文件,用于错误定位。 + * @param context 节点上下文信息(包含行号、列号等)。 */ public record CallExpressionNode( ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名 List arguments, // 函数调用的参数表达式列表 - int line, // 当前节点所在的行号 - int column, // 当前节点所在的列号 - String file // 当前节点所在的文件 + NodeContext context // 节点上下文信息(包含行号、列号等) ) implements ExpressionNode { /** @@ -43,31 +40,4 @@ public record CallExpressionNode( sb.append(")"); // 拼接右括号 return sb.toString(); // 返回拼接好的字符串 } - - /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 - */ - public int line() { - return line; - } - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - public int column() { - return column; - } - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - public String file() { - return file; - } } 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 9e1edf5..dd5bea6 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,14 +24,8 @@ public class DeclarationNode implements StatementNode { /** 可选的初始化表达式 */ private final Optional initializer; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code DeclarationNode} 实例。 @@ -38,14 +33,13 @@ public class DeclarationNode implements StatementNode { * @param name 变量名称 * @param type 变量类型字符串(如 "int"、"string") * @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化 + * @param context 节点上下文信息(包含行号、列号等) */ - public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) { + public DeclarationNode(String name, String type, ExpressionNode initializer, NodeContext context) { this.name = name; this.type = type; this.initializer = Optional.ofNullable(initializer); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -76,27 +70,12 @@ public class DeclarationNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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 1a2f7a5..9b1d821 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。 @@ -11,14 +12,10 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; *

* * @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ExpressionStatementNode( ExpressionNode expression, - int line, - int column, - String file + NodeContext context ) 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 29ab884..d1b29f2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义 * @param returnType 函数的返回类型(如 "int"、"void" 等) * @param body 函数体语句块,由一组 {@link StatementNode} 构成 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record FunctionNode( String name, List parameters, String returnType, List body, - int line, - int column, - String file + NodeContext context ) 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 de0ed17..eb46091 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code IdentifierNode} 表示抽象语法树(AST)中的标识符表达式节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 在语义分析中,通常需要将此类节点绑定到其声明位置或符号表项。 *

* - * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") + * @param context 节点上下文信息(包含行号、列号等) */ public record IdentifierNode( String name, - int line, - int column, - String file + NodeContext context ) 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 a26c8e2..ecc0dd1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -16,29 +17,16 @@ import java.util.List; * 若 condition 为假,则执行 else 分支(如果提供)。 *

*

- * 示例语法结构: - *

- *
{@code
- * if (x > 0) {
- *     print("Positive");
- * } else {
- *     print("Negative");
- * }
- * }
* * @param condition 控制分支执行的条件表达式 * @param thenBranch 条件为 true 时执行的语句块 * @param elseBranch 条件为 false 时执行的语句块(可为空) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record IfNode( ExpressionNode condition, List thenBranch, List elseBranch, - int line, - int column, - String file + NodeContext context ) 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 c6b65e9..a45c751 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。 @@ -14,14 +15,10 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; *

* * @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ImportNode( String moduleName, - int line, - int column, - String file + NodeContext context ) 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 a8ddbe1..2ba283e 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param condition 每次迭代前评估的条件表达式,控制循环是否继续 * @param update 每轮迭代完成后执行的更新语句 * @param body 循环体语句列表,表示循环主体执行逻辑 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号、文件名等) */ public record LoopNode( StatementNode initializer, ExpressionNode condition, StatementNode update, List body, - int line, - int column, - String file + NodeContext context ) 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 d0ac38e..8ab233b 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code MemberExpressionNode} 表示抽象语法树(AST)中的成员访问表达式节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。 *

* - * @param object 左侧对象表达式,表示成员所属的作用域或容器 - * @param member 要访问的成员名称(字段名或方法名) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param object 左侧对象表达式,表示成员所属的作用域或容器 + * @param member 要访问的成员名称(字段名或方法名) + * @param context 节点上下文信息(包含行号、列号等) */ public record MemberExpressionNode( ExpressionNode object, String member, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -35,4 +32,4 @@ public record MemberExpressionNode( public String toString() { return object + "." + member; } -} \ No newline at end of file +} 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 05d47de..84262dd 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; import java.util.StringJoiner; @@ -8,22 +9,17 @@ import java.util.StringJoiner; /** * 表示模块定义的 AST 节点。 * 一个模块通常由模块名、导入语句列表和函数定义列表组成。 - * } * * @param name 模块名称。 * @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。 * @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ModuleNode( String name, List imports, List functions, - int line, - int column, - String file + NodeContext context ) implements Node { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java index 9f253e2..6806112 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code NumberLiteralNode} 表示抽象语法树(AST)中的数字字面量表达式节点。 @@ -11,15 +12,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 数字字面量的原始字符串表示 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record NumberLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** 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 0fbdc18..593d46f 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ParameterNode} 表示抽象语法树(AST)中的函数参数定义节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; * 用于构成函数签名并参与类型检查与函数调用匹配。 *

* - * @param name 参数名称标识符 - * @param type 参数类型字符串(如 "int"、"string") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 参数名称标识符 + * @param type 参数类型字符串(如 "int"、"string") + * @param context 节点上下文信息(包含行号、列号等) */ public record ParameterNode( String name, String type, - int line, - int column, - String file + NodeContext context ) implements Node { /** @@ -35,4 +32,4 @@ public record ParameterNode( public String toString() { return name + ":" + type; } -} \ No newline at end of file +} 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 0fc2254..b6d17e1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,25 +24,18 @@ public class ReturnNode implements StatementNode { /** 可选的返回值表达式 */ private final Optional expression; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code ReturnNode} 实例。 * * @param expression 返回值表达式,如果无返回值则可为 {@code null} + * @param context 节点上下文信息(包含行号、列号等) */ - public ReturnNode(ExpressionNode expression, int line, int column, String file) { + public ReturnNode(ExpressionNode expression, NodeContext context) { this.expression = Optional.ofNullable(expression); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -54,27 +48,12 @@ public class ReturnNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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/StringLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java index daa9f42..dd0e61f 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code StringLiteralNode} 表示抽象语法树(AST)中的字符串字面量表达式节点。 @@ -10,15 +11,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 字符串常量的内容,原始值中不包含双引号 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record StringLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -33,4 +30,4 @@ public record StringLiteralNode( public String toString() { return "\"" + value + "\""; } -} \ 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 7e38ebc..cc22e6a 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。 @@ -15,16 +16,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * * @param operator 一元运算符(仅 "-" 或 "!") * @param operand 运算对象 / 右操作数 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record UnaryExpressionNode( String operator, ExpressionNode operand, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java index 5cba805..8b1e906 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java @@ -17,23 +17,7 @@ package org.jcnc.snow.compiler.parser.ast.base; */ public interface Node { /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 + * 获取节点的上下文(行/列/文件等信息)。 */ - int line(); - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - int column(); - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - String file(); + NodeContext context(); } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java new file mode 100644 index 0000000..e73ce21 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java @@ -0,0 +1,11 @@ +package org.jcnc.snow.compiler.parser.ast.base; + +/** + * NodeContext 记录 AST 节点的位置信息(文件、行、列)。 + */ +public record NodeContext(int line, int column, String file) { + @Override + public String toString() { + return file + ":" + line + ":" + column; + } +} 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 adee8bd..973b81a 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -46,12 +47,9 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i int prec = precedence.ordinal(); // 右侧表达式根据结合性确定优先级绑定 - ExpressionNode right = new PrattExpressionParser().parseExpression( - ctx, - leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1] - ); + ExpressionNode right = new PrattExpressionParser().parseExpression(ctx, leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]); - return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file); + return new BinaryExpressionNode(left, op.getLexeme(), right, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java index cfd49db..677896d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -28,6 +29,6 @@ public class BoolLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new BoolLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new BoolLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } 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 9f5478a..6fd7f4a 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.parser.ast.CallExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -45,7 +46,8 @@ public class CallParselet implements InfixParselet { ctx.getTokens().expect(")"); // 消费并验证 ")" // 创建 CallExpressionNode 并传递位置信息 - return new CallExpressionNode(left, args, line, column, file); + return new CallExpressionNode(left, args, new NodeContext(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 7e46337..f0b9a34 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.IdentifierNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -29,6 +30,6 @@ public class IdentifierParselet implements PrefixParselet { int column = ctx.getTokens().peek(-1).getCol(); String file = ctx.getSourceName(); - return new IdentifierNode(token.getLexeme(), line, column, file); + return new IdentifierNode(token.getLexeme(), new NodeContext(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 ed3cd58..76f1c7f 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -34,7 +35,7 @@ public class MemberParselet implements InfixParselet { String file = ctx.getSourceName(); String member = ts.expectType(TokenType.IDENTIFIER).getLexeme(); - return new MemberExpressionNode(left, member, line, column, file); + return new MemberExpressionNode(left, member, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java index 4b75174..69ac8d7 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -24,6 +25,6 @@ public class NumberLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new NumberLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new NumberLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java index b4eb3b3..542a097 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.StringLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -27,6 +28,6 @@ public class StringLiteralParselet implements PrefixParselet { public ExpressionNode parse(ParserContext ctx, Token token) { String raw = token.getRaw(); String content = raw.substring(1, raw.length() - 1); - return new StringLiteralNode(content, token.getLine(), token.getCol(), ctx.getSourceName()); + return new StringLiteralNode(content, new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of 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 5aedf93..113ab94 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -55,6 +56,6 @@ public class UnaryOperatorParselet implements PrefixParselet { /* ------------------------------------------------------------ * 2. 封装成 AST 节点并返回。 * ------------------------------------------------------------ */ - return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file); + return new UnaryExpressionNode(token.getLexeme(), operand, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java index 75ffbca..c12edb3 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.utils.ASTJsonSerializer; import org.jcnc.snow.compiler.parser.utils.JsonFormatter; @@ -66,8 +67,8 @@ public class ASTPrinter { } } case FunctionNode( - String name, List parameters, String returnType, List body - , int _, int _, String _ + String name, List parameters, String returnType, List body, + NodeContext _ ) -> { System.out.println(pad + "function " + name + "(params=" + parameters + ", return=" + returnType + ")"); @@ -82,11 +83,10 @@ public class ASTPrinter { .orElse(""); System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init); } - case AssignmentNode(String variable, ExpressionNode value, int _, int _, String _) -> + case AssignmentNode(String variable, ExpressionNode value, NodeContext _) -> System.out.println(pad + variable + " = " + value); case IfNode( - ExpressionNode condition, List thenBranch, List elseBranch, int _, - int _, String _ + ExpressionNode condition, List thenBranch, List elseBranch, NodeContext _ ) -> { System.out.println(pad + "if " + condition); for (StatementNode stmt : thenBranch) { @@ -100,8 +100,8 @@ public class ASTPrinter { } } case LoopNode( - StatementNode initializer, ExpressionNode condition, StatementNode update, List body - , int _, int _, String _ + StatementNode initializer, ExpressionNode condition, StatementNode update, List body, + NodeContext _ ) -> { System.out.println(pad + "loop {"); print(initializer, indent + 1); @@ -116,7 +116,7 @@ public class ASTPrinter { } case ReturnNode r -> System.out.println(pad + "return" + r.getExpression().map(e -> " " + e).orElse("")); - case ExpressionStatementNode(ExpressionNode expression, int _, int _, String _) -> + case ExpressionStatementNode(ExpressionNode expression, NodeContext _) -> System.out.println(pad + expression); case null, default -> System.out.println(pad + n); // 回退处理 } 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 a7a3449..3927767 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ParameterNode; @@ -74,7 +75,7 @@ public class FunctionParser implements TopLevelParser { parseFunctionFooter(ts); - return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file); + return new FunctionNode(functionName, parameters, returnType[0], body, new NodeContext(line, column, file)); } /** @@ -194,7 +195,7 @@ public class FunctionParser implements TopLevelParser { String ptype = ts.expectType(TokenType.TYPE).getLexeme(); skipComments(ts); ts.expectType(TokenType.NEWLINE); - list.add(new ParameterNode(pname, ptype, line, column, file)); + list.add(new ParameterNode(pname, ptype, new NodeContext(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 d5443ac..10ca4d5 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.module; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.ast.ImportNode; @@ -57,7 +58,7 @@ public class ImportParser { .getLexeme(); // 创建 ImportNode 节点并加入列表 - imports.add(new ImportNode(mod, line, column, file)); + imports.add(new ImportNode(mod, new NodeContext(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 8a21e70..fc8ff02 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ImportNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -93,6 +94,6 @@ public class ModuleParser implements TopLevelParser { ts.expect("end"); ts.expect("module"); - return new ModuleNode(name, imports, functions, line, column, file); + return new ModuleNode(name, imports, functions, new NodeContext(line, column, 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 2323ada..a7e6fa3 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.DeclarationNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -74,6 +75,6 @@ public class DeclarationStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 返回构建好的声明语法树节点 - return new DeclarationNode(name, type, init, line, column, file); + return new DeclarationNode(name, type, init, new NodeContext(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 f824b6b..36af619 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -56,12 +57,12 @@ public class ExpressionStatementParser implements StatementParser { ts.expect("="); ExpressionNode value = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new AssignmentNode(varName, value, line, column, file); + return new AssignmentNode(varName, value, new NodeContext(line, column, file)); } // 普通表达式语句 ExpressionNode expr = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new ExpressionStatementNode(expr, line, column, file); + return new ExpressionStatementNode(expr, new NodeContext(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 eda8bb1..24d6556 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.IfNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -125,6 +126,6 @@ public class IfStatementParser implements StatementParser { ts.expectType(TokenType.NEWLINE); // 构建并返回 IfNode,包含条件、then 分支和 else 分支 - return new IfNode(condition, thenBranch, elseBranch, line, column, file); + return new IfNode(condition, thenBranch, elseBranch, new NodeContext(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 4422636..c1a9c66 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.LoopNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -116,7 +117,7 @@ public class LoopStatementParser implements StatementParser { ts1.expect("="); ExpressionNode expr = new PrattExpressionParser().parse(ctx1); ts1.expectType(TokenType.NEWLINE); - update[0] = new AssignmentNode(varName, expr, line, column, file); + update[0] = new AssignmentNode(varName, expr, new NodeContext(line, column, file)); ParserUtils.skipNewlines(ts1); } )); @@ -150,6 +151,6 @@ public class LoopStatementParser implements StatementParser { ParserUtils.matchFooter(ts, "loop"); // 返回构造完成的 LoopNode - return new LoopNode(initializer[0], condition[0], update[0], body, loop_line, loop_column, file); + return new LoopNode(initializer[0], condition[0], update[0], body, new NodeContext(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 080f1e6..3b4c6c1 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.ReturnNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -54,6 +55,6 @@ public class ReturnStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 构建并返回 ReturnNode(可能为空表达式) - return new ReturnNode(expr, line, column, file); + return new ReturnNode(expr, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java index 231d9af..278a42c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.utils; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.*; @@ -82,8 +83,7 @@ public class ASTJsonSerializer { return switch (n) { // 模块节点 case ModuleNode( - String name, List imports, List functions, _, int _, - String _ + String name, List imports, List functions, NodeContext _ ) -> { Map map = newNodeMap("Module"); map.put("name", name); @@ -181,34 +181,34 @@ public class ASTJsonSerializer { return switch (expr) { // 二元表达式 case BinaryExpressionNode( - ExpressionNode left, String operator, ExpressionNode right, int _, int _, String _ + ExpressionNode left, String operator, ExpressionNode right, NodeContext _ ) -> exprMap("BinaryExpression", "left", exprToMap(left), "operator", operator, "right", exprToMap(right) ); // 一元表达式 - case UnaryExpressionNode(String operator, ExpressionNode operand, int _, int _, String _) -> + case UnaryExpressionNode(String operator, ExpressionNode operand, NodeContext _) -> exprMap("UnaryExpression", "operator", operator, "operand", exprToMap(operand) ); // 布尔字面量 - case BoolLiteralNode(boolean value, int _, int _, String _) -> exprMap("BoolLiteral", "value", value); + case BoolLiteralNode(boolean value, NodeContext _) -> exprMap("BoolLiteral", "value", value); // 标识符 - case IdentifierNode(String name, int _, int _, String _) -> exprMap("Identifier", "name", name); + case IdentifierNode(String name, NodeContext _) -> exprMap("Identifier", "name", name); // 数字字面量 - case NumberLiteralNode(String value, int _, int _, String _) -> exprMap("NumberLiteral", "value", value); + case NumberLiteralNode(String value, NodeContext _) -> exprMap("NumberLiteral", "value", value); // 字符串字面量 - case StringLiteralNode(String value, int _, int _, String _) -> exprMap("StringLiteral", "value", value); + case StringLiteralNode(String value, NodeContext _) -> exprMap("StringLiteral", "value", value); // 调用表达式 - case CallExpressionNode(ExpressionNode callee, List arguments, int _, int _, String _) -> { + case CallExpressionNode(ExpressionNode callee, List arguments, NodeContext _) -> { List args = new ArrayList<>(arguments.size()); for (ExpressionNode arg : arguments) args.add(exprToMap(arg)); yield exprMap("CallExpression", "callee", exprToMap(callee), "arguments", args); } // 成员访问表达式 - case MemberExpressionNode(ExpressionNode object, String member, int _, int _, String _) -> + case MemberExpressionNode(ExpressionNode object, String member, NodeContext _) -> exprMap("MemberExpression", "object", exprToMap(object), "member", member 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 83c331c..360ec99 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.semantic.analyzers.expression; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer; import org.jcnc.snow.compiler.semantic.core.Context; import org.jcnc.snow.compiler.semantic.core.ModuleInfo; @@ -51,8 +52,8 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer= 0 && col >= 0) ? "行 " + line + ", 列 " + col : "未知位置"); From 65b12ddd4c2aa15b3670b8f13e785bf13954cd02 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:23:54 +0800 Subject: [PATCH 13/62] refactor: OpHelper.java --- .../java/org/jcnc/snow/compiler/backend/utils/OpHelper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java index de873b8..8dc5529 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java @@ -135,7 +135,6 @@ public final class OpHelper { Map revmap = new HashMap<>(); // reverse map OPCODE_MAP.forEach((key, value) -> revmap.put(Integer.parseInt(value), key)); - OPCODE_NAME_MAP = Collections.unmodifiableMap(revmap); } @@ -197,7 +196,7 @@ public final class OpHelper { public static String opcodeName(int code) { String name = OPCODE_NAME_MAP.get(code); if (name == null) { - throw new IllegalStateException("Unknown opcode: " + name); + throw new IllegalStateException("Unknown opcode: " + code); } return name; } From 45eed2aefce247669dcc0488fbfbdba2d42ef717 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 8 Jul 2025 12:39:15 +0800 Subject: [PATCH 14/62] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20AST?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E4=B8=AD=E7=9A=84=E4=BD=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=A1=A8=E7=A4=BA=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 NodeContext 类统一表示节点的上下文信息(行号、列号、文件名) - 修改相关 AST 节点的构造函数,使用 NodeContext 替代单独的行号、列号和文件名参数 - 更新解析器代码,创建 NodeContext 实例以传递给 AST节点 - 此重构简化了 AST 节点的参数列表,提高了代码的可维护性和可读性 --- .../compiler/ir/builder/IRProgramBuilder.java | 5 +-- .../compiler/ir/builder/StatementBuilder.java | 9 ++-- .../compiler/ir/utils/ComparisonUtils.java | 3 +- .../compiler/ir/utils/ExpressionUtils.java | 3 +- .../compiler/parser/ast/AssignmentNode.java | 11 ++--- .../parser/ast/BinaryExpressionNode.java | 9 ++-- .../compiler/parser/ast/BoolLiteralNode.java | 18 ++++---- .../parser/ast/CallExpressionNode.java | 36 ++------------- .../compiler/parser/ast/DeclarationNode.java | 45 +++++-------------- .../parser/ast/ExpressionStatementNode.java | 11 ++--- .../compiler/parser/ast/FunctionNode.java | 11 ++--- .../compiler/parser/ast/IdentifierNode.java | 11 ++--- .../jcnc/snow/compiler/parser/ast/IfNode.java | 20 ++------- .../snow/compiler/parser/ast/ImportNode.java | 11 ++--- .../snow/compiler/parser/ast/LoopNode.java | 11 ++--- .../parser/ast/MemberExpressionNode.java | 15 +++---- .../snow/compiler/parser/ast/ModuleNode.java | 10 ++--- .../parser/ast/NumberLiteralNode.java | 9 ++-- .../compiler/parser/ast/ParameterNode.java | 15 +++---- .../snow/compiler/parser/ast/ReturnNode.java | 45 +++++-------------- .../parser/ast/StringLiteralNode.java | 11 ++--- .../parser/ast/UnaryExpressionNode.java | 9 ++-- .../snow/compiler/parser/ast/base/Node.java | 20 +-------- .../compiler/parser/ast/base/NodeContext.java | 11 +++++ .../expression/BinaryOperatorParselet.java | 8 ++-- .../expression/BoolLiteralParselet.java | 3 +- .../parser/expression/CallParselet.java | 4 +- .../parser/expression/IdentifierParselet.java | 3 +- .../parser/expression/MemberParselet.java | 3 +- .../expression/NumberLiteralParselet.java | 3 +- .../expression/StringLiteralParselet.java | 3 +- .../expression/UnaryOperatorParselet.java | 3 +- .../compiler/parser/function/ASTPrinter.java | 16 +++---- .../parser/function/FunctionParser.java | 5 ++- .../compiler/parser/module/ImportParser.java | 3 +- .../compiler/parser/module/ModuleParser.java | 3 +- .../statement/DeclarationStatementParser.java | 3 +- .../statement/ExpressionStatementParser.java | 5 ++- .../parser/statement/IfStatementParser.java | 3 +- .../parser/statement/LoopStatementParser.java | 5 ++- .../statement/ReturnStatementParser.java | 3 +- .../parser/utils/ASTJsonSerializer.java | 20 ++++----- .../expression/CallExpressionAnalyzer.java | 7 +-- .../semantic/error/SemanticError.java | 7 +-- 44 files changed, 177 insertions(+), 292 deletions(-) create mode 100644 src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java 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 5513fdc..225743e 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 @@ -5,6 +5,7 @@ import org.jcnc.snow.compiler.ir.core.IRProgram; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -81,9 +82,7 @@ public final class IRProgramBuilder { null, String.valueOf(List.of()), List.of(stmt), - -1, - -1, - "" + new NodeContext(-1, -1, "") ); } } 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 557634b..78e42fa 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 @@ -6,6 +6,7 @@ import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.Locale; @@ -66,12 +67,12 @@ public class StatementBuilder { buildIf(ifNode); return; } - if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, int _, int _, String _)) { + if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, NodeContext _)) { // 纯表达式语句,如 foo(); expr.build(exp); return; } - if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, int _, int _, String _)) { + if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, NodeContext _)) { // 赋值语句,如 a = b + 1; final String type = ctx.getScope().lookupType(var); @@ -209,9 +210,7 @@ public class StatementBuilder { ExpressionNode left, String operator, ExpressionNode right, - _, - _, - _ + NodeContext _ ) && ComparisonUtils.isComparisonOperator(operator)) { diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java index 08b42b8..70ac8f5 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.ir.core.IROpCode; import org.jcnc.snow.compiler.ir.core.IROpCodeMappings; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -41,7 +42,7 @@ public final class ComparisonUtils { /* ------------ 内部工具 ------------ */ private static boolean isLongLiteral(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { return value.endsWith("L") || value.endsWith("l"); } return false; // 变量暂不处理(后续可扩展符号表查询) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java index 291b861..2eed575 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java @@ -7,6 +7,7 @@ import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Map; @@ -127,7 +128,7 @@ public final class ExpressionUtils { /** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */ private static char typeChar(ExpressionNode node) { - if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) { + if (node instanceof NumberLiteralNode(String value, NodeContext _)) { char last = Character.toLowerCase(value.charAt(value.length() - 1)); return switch (last) { case 'b','s','i','l','f','d' -> last; 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 eace610..34b387c 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。 @@ -16,16 +17,12 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; * * @param variable 左值变量名(即赋值目标) * @param value 表达式右值(即赋值来源) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号等) */ public record AssignmentNode( String variable, ExpressionNode value, - int line, - int column, - String file + NodeContext context ) implements StatementNode { /** @@ -40,4 +37,4 @@ public record AssignmentNode( public String toString() { return variable + " = " + value; } -} \ No newline at end of file +} 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 40412de..ec56cc2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code BinaryExpressionNode} 表示抽象语法树(AST)中的二元运算表达式节点。 @@ -12,17 +13,13 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * @param left 左操作数(子表达式) * @param operator 运算符字符串(如 "+", "-", "*", "/" 等) * @param right 右操作数(子表达式) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文(包含行号、列号等信息) */ public record BinaryExpressionNode( ExpressionNode left, String operator, ExpressionNode right, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java index bb46a30..909a43c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 表达布尔类型的字面量常量(如 "true" 或 "false")。 *

* - * @param value 字面量的布尔值 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param value 字面量的布尔值 + * @param context 节点上下文信息(行号、列号等) */ public record BoolLiteralNode( boolean value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -28,10 +25,11 @@ public record BoolLiteralNode( * 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。 *

* - * @param lexeme 布尔字面量的字符串表示 + * @param lexeme 布尔字面量的字符串表示 + * @param context 节点上下文信息(行号、列号等) */ - public BoolLiteralNode(String lexeme, int line, int column, String file) { - this(Boolean.parseBoolean(lexeme), line, column, file); + public BoolLiteralNode(String lexeme, NodeContext context) { + this(Boolean.parseBoolean(lexeme), context); } /** 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 d7dbce9..8033989 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -12,16 +13,12 @@ import java.util.List; * * @param callee 被调用的表达式节点,通常为函数标识符或成员访问表达式,表示函数名或方法名等。 * @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。 - * @param line 当前表达式所在的行号,方便调试和错误定位。 - * @param column 当前表达式所在的列号,用于精确定位错误位置。 - * @param file 当前表达式所在的文件,用于错误定位。 + * @param context 节点上下文信息(包含行号、列号等)。 */ public record CallExpressionNode( ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名 List arguments, // 函数调用的参数表达式列表 - int line, // 当前节点所在的行号 - int column, // 当前节点所在的列号 - String file // 当前节点所在的文件 + NodeContext context // 节点上下文信息(包含行号、列号等) ) implements ExpressionNode { /** @@ -43,31 +40,4 @@ public record CallExpressionNode( sb.append(")"); // 拼接右括号 return sb.toString(); // 返回拼接好的字符串 } - - /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 - */ - public int line() { - return line; - } - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - public int column() { - return column; - } - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - public String file() { - return file; - } } 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 9e1edf5..dd5bea6 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,14 +24,8 @@ public class DeclarationNode implements StatementNode { /** 可选的初始化表达式 */ private final Optional initializer; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code DeclarationNode} 实例。 @@ -38,14 +33,13 @@ public class DeclarationNode implements StatementNode { * @param name 变量名称 * @param type 变量类型字符串(如 "int"、"string") * @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化 + * @param context 节点上下文信息(包含行号、列号等) */ - public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) { + public DeclarationNode(String name, String type, ExpressionNode initializer, NodeContext context) { this.name = name; this.type = type; this.initializer = Optional.ofNullable(initializer); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -76,27 +70,12 @@ public class DeclarationNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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 1a2f7a5..9b1d821 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。 @@ -11,14 +12,10 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; *

* * @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ExpressionStatementNode( ExpressionNode expression, - int line, - int column, - String file + NodeContext context ) 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 29ab884..d1b29f2 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义 * @param returnType 函数的返回类型(如 "int"、"void" 等) * @param body 函数体语句块,由一组 {@link StatementNode} 构成 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record FunctionNode( String name, List parameters, String returnType, List body, - int line, - int column, - String file + NodeContext context ) 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 de0ed17..eb46091 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code IdentifierNode} 表示抽象语法树(AST)中的标识符表达式节点。 @@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 在语义分析中,通常需要将此类节点绑定到其声明位置或符号表项。 *

* - * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 标识符的文本名称(如变量名 "x",函数名 "foo") + * @param context 节点上下文信息(包含行号、列号等) */ public record IdentifierNode( String name, - int line, - int column, - String file + NodeContext context ) 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 a26c8e2..ecc0dd1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; @@ -16,29 +17,16 @@ import java.util.List; * 若 condition 为假,则执行 else 分支(如果提供)。 *

*

- * 示例语法结构: - *

- *
{@code
- * if (x > 0) {
- *     print("Positive");
- * } else {
- *     print("Negative");
- * }
- * }
* * @param condition 控制分支执行的条件表达式 * @param thenBranch 条件为 true 时执行的语句块 * @param elseBranch 条件为 false 时执行的语句块(可为空) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record IfNode( ExpressionNode condition, List thenBranch, List elseBranch, - int line, - int column, - String file + NodeContext context ) 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 c6b65e9..a45c751 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。 @@ -14,14 +15,10 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; *

* * @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ImportNode( String moduleName, - int line, - int column, - String file + NodeContext context ) 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 a8ddbe1..2ba283e 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.List; @@ -17,17 +18,13 @@ import java.util.List; * @param condition 每次迭代前评估的条件表达式,控制循环是否继续 * @param update 每轮迭代完成后执行的更新语句 * @param body 循环体语句列表,表示循环主体执行逻辑 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点的上下文信息(包含行号、列号、文件名等) */ public record LoopNode( StatementNode initializer, ExpressionNode condition, StatementNode update, List body, - int line, - int column, - String file + NodeContext context ) 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 d0ac38e..8ab233b 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code MemberExpressionNode} 表示抽象语法树(AST)中的成员访问表达式节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。 *

* - * @param object 左侧对象表达式,表示成员所属的作用域或容器 - * @param member 要访问的成员名称(字段名或方法名) - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param object 左侧对象表达式,表示成员所属的作用域或容器 + * @param member 要访问的成员名称(字段名或方法名) + * @param context 节点上下文信息(包含行号、列号等) */ public record MemberExpressionNode( ExpressionNode object, String member, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -35,4 +32,4 @@ public record MemberExpressionNode( public String toString() { return object + "." + member; } -} \ No newline at end of file +} 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 05d47de..84262dd 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.List; import java.util.StringJoiner; @@ -8,22 +9,17 @@ import java.util.StringJoiner; /** * 表示模块定义的 AST 节点。 * 一个模块通常由模块名、导入语句列表和函数定义列表组成。 - * } * * @param name 模块名称。 * @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。 * @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record ModuleNode( String name, List imports, List functions, - int line, - int column, - String file + NodeContext context ) implements Node { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java index 9f253e2..6806112 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code NumberLiteralNode} 表示抽象语法树(AST)中的数字字面量表达式节点。 @@ -11,15 +12,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 数字字面量的原始字符串表示 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record NumberLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** 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 0fbdc18..593d46f 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code ParameterNode} 表示抽象语法树(AST)中的函数参数定义节点。 @@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; * 用于构成函数签名并参与类型检查与函数调用匹配。 *

* - * @param name 参数名称标识符 - * @param type 参数类型字符串(如 "int"、"string") - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param name 参数名称标识符 + * @param type 参数类型字符串(如 "int"、"string") + * @param context 节点上下文信息(包含行号、列号等) */ public record ParameterNode( String name, String type, - int line, - int column, - String file + NodeContext context ) implements Node { /** @@ -35,4 +32,4 @@ public record ParameterNode( public String toString() { return name + ":" + type; } -} \ No newline at end of file +} 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 0fc2254..b6d17e1 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.Optional; @@ -23,25 +24,18 @@ public class ReturnNode implements StatementNode { /** 可选的返回值表达式 */ private final Optional expression; - /** 当前节点所在的行号 **/ - private final int line; - - /** 当前节点所在的列号 **/ - private final int column; - - /** 当前节点所在的文件 **/ - private final String file; + /** 节点上下文信息(包含行号、列号等) */ + private final NodeContext context; /** * 构造一个 {@code ReturnNode} 实例。 * * @param expression 返回值表达式,如果无返回值则可为 {@code null} + * @param context 节点上下文信息(包含行号、列号等) */ - public ReturnNode(ExpressionNode expression, int line, int column, String file) { + public ReturnNode(ExpressionNode expression, NodeContext context) { this.expression = Optional.ofNullable(expression); - this.line = line; - this.column = column; - this.file = file; + this.context = context; } /** @@ -54,27 +48,12 @@ public class ReturnNode implements StatementNode { } /** - * 获取当前表达式所在的行号。 + * 获取节点上下文信息(包含行号、列号等)。 * - * @return 当前表达式的行号。 + * @return NodeContext 实例 */ - public int line() { - return line; + @Override + public NodeContext context() { + return context; } - - /** - * 获取当前表达式所在的列号。 - * - * @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/StringLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java index daa9f42..dd0e61f 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code StringLiteralNode} 表示抽象语法树(AST)中的字符串字面量表达式节点。 @@ -10,15 +11,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; *

* * @param value 字符串常量的内容,原始值中不包含双引号 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record StringLiteralNode( String value, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** @@ -33,4 +30,4 @@ public record StringLiteralNode( public String toString() { return "\"" + value + "\""; } -} \ 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 7e38ebc..cc22e6a 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.ast; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。 @@ -15,16 +16,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; * * @param operator 一元运算符(仅 "-" 或 "!") * @param operand 运算对象 / 右操作数 - * @param line 当前节点所在的行号 - * @param column 当前节点所在的列号 - * @param file 当前节点所在的文件 + * @param context 节点上下文信息(包含行号、列号等) */ public record UnaryExpressionNode( String operator, ExpressionNode operand, - int line, - int column, - String file + NodeContext context ) implements ExpressionNode { /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java index 5cba805..8b1e906 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/Node.java @@ -17,23 +17,7 @@ package org.jcnc.snow.compiler.parser.ast.base; */ public interface Node { /** - * 获取当前表达式所在的行号。 - * - * @return 当前表达式的行号。 + * 获取节点的上下文(行/列/文件等信息)。 */ - int line(); - - /** - * 获取当前表达式所在的列号。 - * - * @return 当前表达式的列号。 - */ - int column(); - - /** - * 获取当前表达式所在的文件名。 - * - * @return 当前表达式所在的文件名。 - */ - String file(); + NodeContext context(); } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java new file mode 100644 index 0000000..e73ce21 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/NodeContext.java @@ -0,0 +1,11 @@ +package org.jcnc.snow.compiler.parser.ast.base; + +/** + * NodeContext 记录 AST 节点的位置信息(文件、行、列)。 + */ +public record NodeContext(int line, int column, String file) { + @Override + public String toString() { + return file + ":" + line + ":" + column; + } +} 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 adee8bd..973b81a 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -46,12 +47,9 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i int prec = precedence.ordinal(); // 右侧表达式根据结合性确定优先级绑定 - ExpressionNode right = new PrattExpressionParser().parseExpression( - ctx, - leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1] - ); + ExpressionNode right = new PrattExpressionParser().parseExpression(ctx, leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]); - return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file); + return new BinaryExpressionNode(left, op.getLexeme(), right, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java index cfd49db..677896d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -28,6 +29,6 @@ public class BoolLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new BoolLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new BoolLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } 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 9f5478a..6fd7f4a 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.parser.ast.CallExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -45,7 +46,8 @@ public class CallParselet implements InfixParselet { ctx.getTokens().expect(")"); // 消费并验证 ")" // 创建 CallExpressionNode 并传递位置信息 - return new CallExpressionNode(left, args, line, column, file); + return new CallExpressionNode(left, args, new NodeContext(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 7e46337..f0b9a34 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.IdentifierNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -29,6 +30,6 @@ public class IdentifierParselet implements PrefixParselet { int column = ctx.getTokens().peek(-1).getCol(); String file = ctx.getSourceName(); - return new IdentifierNode(token.getLexeme(), line, column, file); + return new IdentifierNode(token.getLexeme(), new NodeContext(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 ed3cd58..76f1c7f 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; import org.jcnc.snow.compiler.parser.expression.base.InfixParselet; @@ -34,7 +35,7 @@ public class MemberParselet implements InfixParselet { String file = ctx.getSourceName(); String member = ts.expectType(TokenType.IDENTIFIER).getLexeme(); - return new MemberExpressionNode(left, member, line, column, file); + return new MemberExpressionNode(left, member, new NodeContext(line, column, file)); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java index 4b75174..69ac8d7 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -24,6 +25,6 @@ public class NumberLiteralParselet implements PrefixParselet { */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { - return new NumberLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName()); + return new NumberLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java index b4eb3b3..542a097 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.StringLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -27,6 +28,6 @@ public class StringLiteralParselet implements PrefixParselet { public ExpressionNode parse(ParserContext ctx, Token token) { String raw = token.getRaw(); String content = raw.substring(1, raw.length() - 1); - return new StringLiteralNode(content, token.getLine(), token.getCol(), ctx.getSourceName()); + return new StringLiteralNode(content, new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName())); } } \ No newline at end of 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 5aedf93..113ab94 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; @@ -55,6 +56,6 @@ public class UnaryOperatorParselet implements PrefixParselet { /* ------------------------------------------------------------ * 2. 封装成 AST 节点并返回。 * ------------------------------------------------------------ */ - return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file); + return new UnaryExpressionNode(token.getLexeme(), operand, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java index 75ffbca..c12edb3 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/function/ASTPrinter.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.utils.ASTJsonSerializer; import org.jcnc.snow.compiler.parser.utils.JsonFormatter; @@ -66,8 +67,8 @@ public class ASTPrinter { } } case FunctionNode( - String name, List parameters, String returnType, List body - , int _, int _, String _ + String name, List parameters, String returnType, List body, + NodeContext _ ) -> { System.out.println(pad + "function " + name + "(params=" + parameters + ", return=" + returnType + ")"); @@ -82,11 +83,10 @@ public class ASTPrinter { .orElse(""); System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init); } - case AssignmentNode(String variable, ExpressionNode value, int _, int _, String _) -> + case AssignmentNode(String variable, ExpressionNode value, NodeContext _) -> System.out.println(pad + variable + " = " + value); case IfNode( - ExpressionNode condition, List thenBranch, List elseBranch, int _, - int _, String _ + ExpressionNode condition, List thenBranch, List elseBranch, NodeContext _ ) -> { System.out.println(pad + "if " + condition); for (StatementNode stmt : thenBranch) { @@ -100,8 +100,8 @@ public class ASTPrinter { } } case LoopNode( - StatementNode initializer, ExpressionNode condition, StatementNode update, List body - , int _, int _, String _ + StatementNode initializer, ExpressionNode condition, StatementNode update, List body, + NodeContext _ ) -> { System.out.println(pad + "loop {"); print(initializer, indent + 1); @@ -116,7 +116,7 @@ public class ASTPrinter { } case ReturnNode r -> System.out.println(pad + "return" + r.getExpression().map(e -> " " + e).orElse("")); - case ExpressionStatementNode(ExpressionNode expression, int _, int _, String _) -> + case ExpressionStatementNode(ExpressionNode expression, NodeContext _) -> System.out.println(pad + expression); case null, default -> System.out.println(pad + n); // 回退处理 } 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 a7a3449..3927767 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.function; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ParameterNode; @@ -74,7 +75,7 @@ public class FunctionParser implements TopLevelParser { parseFunctionFooter(ts); - return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file); + return new FunctionNode(functionName, parameters, returnType[0], body, new NodeContext(line, column, file)); } /** @@ -194,7 +195,7 @@ public class FunctionParser implements TopLevelParser { String ptype = ts.expectType(TokenType.TYPE).getLexeme(); skipComments(ts); ts.expectType(TokenType.NEWLINE); - list.add(new ParameterNode(pname, ptype, line, column, file)); + list.add(new ParameterNode(pname, ptype, new NodeContext(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 d5443ac..10ca4d5 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 @@ -1,6 +1,7 @@ package org.jcnc.snow.compiler.parser.module; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.ast.ImportNode; @@ -57,7 +58,7 @@ public class ImportParser { .getLexeme(); // 创建 ImportNode 节点并加入列表 - imports.add(new ImportNode(mod, line, column, file)); + imports.add(new ImportNode(mod, new NodeContext(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 8a21e70..fc8ff02 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ImportNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -93,6 +94,6 @@ public class ModuleParser implements TopLevelParser { ts.expect("end"); ts.expect("module"); - return new ModuleNode(name, imports, functions, line, column, file); + return new ModuleNode(name, imports, functions, new NodeContext(line, column, 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 2323ada..a7e6fa3 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.DeclarationNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -74,6 +75,6 @@ public class DeclarationStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 返回构建好的声明语法树节点 - return new DeclarationNode(name, type, init, line, column, file); + return new DeclarationNode(name, type, init, new NodeContext(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 f824b6b..36af619 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -56,12 +57,12 @@ public class ExpressionStatementParser implements StatementParser { ts.expect("="); ExpressionNode value = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new AssignmentNode(varName, value, line, column, file); + return new AssignmentNode(varName, value, new NodeContext(line, column, file)); } // 普通表达式语句 ExpressionNode expr = new PrattExpressionParser().parse(ctx); ts.expectType(TokenType.NEWLINE); - return new ExpressionStatementNode(expr, line, column, file); + return new ExpressionStatementNode(expr, new NodeContext(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 eda8bb1..24d6556 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.IfNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -125,6 +126,6 @@ public class IfStatementParser implements StatementParser { ts.expectType(TokenType.NEWLINE); // 构建并返回 IfNode,包含条件、then 分支和 else 分支 - return new IfNode(condition, thenBranch, elseBranch, line, column, file); + return new IfNode(condition, thenBranch, elseBranch, new NodeContext(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 4422636..c1a9c66 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 @@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.AssignmentNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.LoopNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.TokenStream; @@ -116,7 +117,7 @@ public class LoopStatementParser implements StatementParser { ts1.expect("="); ExpressionNode expr = new PrattExpressionParser().parse(ctx1); ts1.expectType(TokenType.NEWLINE); - update[0] = new AssignmentNode(varName, expr, line, column, file); + update[0] = new AssignmentNode(varName, expr, new NodeContext(line, column, file)); ParserUtils.skipNewlines(ts1); } )); @@ -150,6 +151,6 @@ public class LoopStatementParser implements StatementParser { ParserUtils.matchFooter(ts, "loop"); // 返回构造完成的 LoopNode - return new LoopNode(initializer[0], condition[0], update[0], body, loop_line, loop_column, file); + return new LoopNode(initializer[0], condition[0], update[0], body, new NodeContext(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 080f1e6..3b4c6c1 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 @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement; import org.jcnc.snow.compiler.lexer.token.TokenType; import org.jcnc.snow.compiler.parser.ast.ReturnNode; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; @@ -54,6 +55,6 @@ public class ReturnStatementParser implements StatementParser { ctx.getTokens().expectType(TokenType.NEWLINE); // 构建并返回 ReturnNode(可能为空表达式) - return new ReturnNode(expr, line, column, file); + return new ReturnNode(expr, new NodeContext(line, column, file)); } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java index 231d9af..278a42c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTJsonSerializer.java @@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.utils; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import java.util.*; @@ -82,8 +83,7 @@ public class ASTJsonSerializer { return switch (n) { // 模块节点 case ModuleNode( - String name, List imports, List functions, _, int _, - String _ + String name, List imports, List functions, NodeContext _ ) -> { Map map = newNodeMap("Module"); map.put("name", name); @@ -181,34 +181,34 @@ public class ASTJsonSerializer { return switch (expr) { // 二元表达式 case BinaryExpressionNode( - ExpressionNode left, String operator, ExpressionNode right, int _, int _, String _ + ExpressionNode left, String operator, ExpressionNode right, NodeContext _ ) -> exprMap("BinaryExpression", "left", exprToMap(left), "operator", operator, "right", exprToMap(right) ); // 一元表达式 - case UnaryExpressionNode(String operator, ExpressionNode operand, int _, int _, String _) -> + case UnaryExpressionNode(String operator, ExpressionNode operand, NodeContext _) -> exprMap("UnaryExpression", "operator", operator, "operand", exprToMap(operand) ); // 布尔字面量 - case BoolLiteralNode(boolean value, int _, int _, String _) -> exprMap("BoolLiteral", "value", value); + case BoolLiteralNode(boolean value, NodeContext _) -> exprMap("BoolLiteral", "value", value); // 标识符 - case IdentifierNode(String name, int _, int _, String _) -> exprMap("Identifier", "name", name); + case IdentifierNode(String name, NodeContext _) -> exprMap("Identifier", "name", name); // 数字字面量 - case NumberLiteralNode(String value, int _, int _, String _) -> exprMap("NumberLiteral", "value", value); + case NumberLiteralNode(String value, NodeContext _) -> exprMap("NumberLiteral", "value", value); // 字符串字面量 - case StringLiteralNode(String value, int _, int _, String _) -> exprMap("StringLiteral", "value", value); + case StringLiteralNode(String value, NodeContext _) -> exprMap("StringLiteral", "value", value); // 调用表达式 - case CallExpressionNode(ExpressionNode callee, List arguments, int _, int _, String _) -> { + case CallExpressionNode(ExpressionNode callee, List arguments, NodeContext _) -> { List args = new ArrayList<>(arguments.size()); for (ExpressionNode arg : arguments) args.add(exprToMap(arg)); yield exprMap("CallExpression", "callee", exprToMap(callee), "arguments", args); } // 成员访问表达式 - case MemberExpressionNode(ExpressionNode object, String member, int _, int _, String _) -> + case MemberExpressionNode(ExpressionNode object, String member, NodeContext _) -> exprMap("MemberExpression", "object", exprToMap(object), "member", member 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 83c331c..360ec99 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 @@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.semantic.analyzers.expression; import org.jcnc.snow.compiler.parser.ast.*; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer; import org.jcnc.snow.compiler.semantic.core.Context; import org.jcnc.snow.compiler.semantic.core.ModuleInfo; @@ -51,8 +52,8 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer= 0 && col >= 0) ? "行 " + line + ", 列 " + col : "未知位置"); From 2a25abcf035b5349a247b39dd787426c12c9733e Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:23:54 +0800 Subject: [PATCH 15/62] refactor: OpHelper.java --- .../java/org/jcnc/snow/compiler/backend/utils/OpHelper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java index de873b8..8dc5529 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/utils/OpHelper.java @@ -135,7 +135,6 @@ public final class OpHelper { Map revmap = new HashMap<>(); // reverse map OPCODE_MAP.forEach((key, value) -> revmap.put(Integer.parseInt(value), key)); - OPCODE_NAME_MAP = Collections.unmodifiableMap(revmap); } @@ -197,7 +196,7 @@ public final class OpHelper { public static String opcodeName(int code) { String name = OPCODE_NAME_MAP.get(code); if (name == null) { - throw new IllegalStateException("Unknown opcode: " + name); + throw new IllegalStateException("Unknown opcode: " + code); } return name; } From c83a584795b9b81da7add2ce54532e61fbb1baa0 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 9 Jul 2025 23:58:46 +0800 Subject: [PATCH 16/62] =?UTF-8?q?fix:=20=E5=9C=A8=E9=9D=9E=20void=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E4=B8=AD=E5=BC=BA=E5=88=B6=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20return=20=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 FunctionChecker 中添加一个检查,以确保具有非 void 返回类型的功能 类型必须至少包含一个返回节点。否则将引发语义错误。 --- .../compiler/semantic/core/FunctionChecker.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java index e6d69c3..66385b6 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/FunctionChecker.java @@ -2,11 +2,13 @@ package org.jcnc.snow.compiler.semantic.core; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.ReturnNode; import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer; import org.jcnc.snow.compiler.semantic.error.SemanticError; import org.jcnc.snow.compiler.semantic.symbol.Symbol; import org.jcnc.snow.compiler.semantic.symbol.SymbolKind; import org.jcnc.snow.compiler.semantic.symbol.SymbolTable; +import org.jcnc.snow.compiler.semantic.type.BuiltinType; /** * {@code FunctionChecker} 是语义分析阶段中用于检查函数体语句合法性的调度器。 @@ -79,6 +81,19 @@ public record FunctionChecker(Context ctx) { )); } } + + // 检查非 void 函数是否至少包含一条 return 语句 + var returnType = ctx.parseType(fn.returnType()); + if (returnType != BuiltinType.VOID) { + boolean hasReturn = fn.body().stream() + .anyMatch(stmtNode -> stmtNode instanceof ReturnNode); + if (!hasReturn) { + ctx.errors().add(new SemanticError( + fn, + "非 void 函数必须包含至少一条 return 语句" + )); + } + } } } } From 2289cf3ee4b0c6a9fbcd88dbd733ff7092a5577d Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:28:12 +0800 Subject: [PATCH 17/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20byte8=20?= =?UTF-8?q?=E8=BD=AC=20short16=E3=80=81long64=E3=80=81float32=E3=80=81doub?= =?UTF-8?q?le64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/B2DCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2FCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2LCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/B2SCommand.java | 47 +++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java new file mode 100644 index 0000000..1ca0655 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2DCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2DCommand Opcode: Represents the type conversion operation from byte8 to double64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2DCommand implements Command { + + /** + * Default constructor for creating an instance of B2DCommand. + */ + public B2DCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to double64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java new file mode 100644 index 0000000..c61891b --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2FCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2FCommand Opcode: Represents the type conversion operation from byte8 to float32 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a float32 value.
  4. + *
  5. Push the converted float32 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2FCommand implements Command { + + /** + * Default constructor for creating an instance of B2FCommand. + */ + public B2FCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to float32 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java new file mode 100644 index 0000000..344b49d --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2LCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2LCommand Opcode: Represents the type conversion operation from byte8 to long64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2LCommand implements Command { + + /** + * Default constructor for creating an instance of B2LCommand. + */ + public B2LCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to long64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java new file mode 100644 index 0000000..1f09ff9 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/B2SCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * B2SCommand Opcode: Represents the type conversion operation from byte8 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top byte8 value from the operand stack.
  2. + *
  3. Convert the byte8 value to a short16 value.
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ +public class B2SCommand implements Command { + + /** + * Default constructor for creating an instance of B2SCommand. + */ + public B2SCommand() { + // Empty constructor + } + + /** + * Executes the byte8 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + short convertedValue = (byte) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 9e2eb6731f1029bbe1e14f4aa26b31038395aca0 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 20:31:16 +0800 Subject: [PATCH 18/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20short16=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81long64=E3=80=81float32=E3=80=81double?= =?UTF-8?q?64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/S2BCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2DCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2FCommand.java | 47 +++++++++++++++++++ .../commands/type/conversion/S2LCommand.java | 47 +++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java new file mode 100644 index 0000000..fa86e5f --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2BCommand Opcode: Represents the type conversion operation from short16 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to a byte8 value.
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to a byte8 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2BCommand implements Command { + + /** + * Default constructor for creating an instance of S2BCommand. + */ + public S2BCommand() { + // Empty constructor + } + + /** + * Executes the short16 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + byte convertedValue = (byte) ((short) operandStack.pop()); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java new file mode 100644 index 0000000..2f3381f --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2DCommand Opcode: Represents the type conversion operation from short16 to double64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to an double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to an double64 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2DCommand implements Command { + + /** + * Default constructor for creating an instance of S2DCommand. + */ + public S2DCommand() { + // Empty constructor + } + + /** + * Executes the short16 to double64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java new file mode 100644 index 0000000..78fbb4a --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2FCommand Opcode: Represents the type conversion operation from short16 to float32 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to an float32 value.
  4. + *
  5. Push the converted float32 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to an float32 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2FCommand implements Command { + + /** + * Default constructor for creating an instance of S2FCommand. + */ + public S2FCommand() { + // Empty constructor + } + + /** + * Executes the short16 to float32 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java new file mode 100644 index 0000000..cec58e6 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2LCommand.java @@ -0,0 +1,47 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * S2LCommand Opcode: Represents the type conversion operation from short16 to long64 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top short16 value from the operand stack.
  2. + *
  3. Convert the short16 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a short16 value to a long64 type, facilitating subsequent integer arithmetic or comparison operations.

+ */ +public class S2LCommand implements Command { + + /** + * Default constructor for creating an instance of S2LCommand. + */ + public S2LCommand() { + // Empty constructor + } + + /** + * Executes the short16 to long64 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long convertedValue = (short) operandStack.pop(); + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 4595583ca4bba4e318124536891702cfe81347ed Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:00:09 +0800 Subject: [PATCH 19/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20double64=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/D2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/D2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java new file mode 100644 index 0000000..7180d2e --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * D2BCommand Opcode: Represents the type conversion operation from double64 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top double64 value from the operand stack.
  2. + *
  3. Convert the double64 value to a byte8 value (this may involve truncation).
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to narrow a double64 value to a byte8 type for further integer-based operations.

+ */ +public class D2BCommand implements Command { + + /** + * Default constructor for creating an instance of D2BCommand. + */ + public D2BCommand() { + // Empty constructor + } + + /** + * Executes the double64 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double value = (double) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java new file mode 100644 index 0000000..ab11cf0 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * D2SCommand Opcode: Represents the type conversion operation from double64 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top double64 value from the operand stack.
  2. + *
  3. Convert the double64 value to an short16 value (this may involve truncation).
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to narrow a double64 value to an short16 type for further integer-based operations.

+ */ +public class D2SCommand implements Command { + + /** + * Default constructor for creating an instance of D2SCommand. + */ + public D2SCommand() { + // Empty constructor + } + + /** + * Executes the double64 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + double value = (double) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 85fae69c971dabe06a3cebdd7276496d9b115252 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:02:30 +0800 Subject: [PATCH 20/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20float32=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/F2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/F2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java new file mode 100644 index 0000000..5240f86 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * F2BCommand Opcode: Represents the type conversion operation from float32 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top float32 value from the operand stack.
  2. + *
  3. Convert the float32 value to a byte8 value (this may involve truncation).
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to convert a float32 value to a byte8 type for further integer operations or comparisons.

+ */ +public class F2BCommand implements Command { + + /** + * Default constructor for creating an instance of F2BCommand. + */ + public F2BCommand() { + // Empty constructor + } + + /** + * Executes the float32 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float value = (float) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java new file mode 100644 index 0000000..83a79b5 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/F2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * F2SCommand Opcode: Represents the type conversion operation from float32 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top float32 value from the operand stack.
  2. + *
  3. Convert the float32 value to a short16 value (this may involve truncation).
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to convert a float32 value to a short16 type for further integer operations or comparisons.

+ */ +public class F2SCommand implements Command { + + /** + * Default constructor for creating an instance of F2SCommand. + */ + public F2SCommand() { + // Empty constructor + } + + /** + * Executes the float32 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + float value = (float) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 9c69c1f37ba6cd5f718ec1a639e0d6781bc1f0a0 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:04:23 +0800 Subject: [PATCH 21/62] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20long64=20?= =?UTF-8?q?=E8=BD=AC=20byte8=E3=80=81short16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/type/conversion/L2BCommand.java | 48 +++++++++++++++++++ .../commands/type/conversion/L2SCommand.java | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java create mode 100644 src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java new file mode 100644 index 0000000..cde429c --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2BCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * L2BCommand Opcode: Represents the type conversion operation from long64 to byte8 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a byte8 value.
  4. + *
  5. Push the converted byte8 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a byte8 type for high-precision floating-point computations.

+ */ +public class L2BCommand implements Command { + + /** + * Default constructor for creating an instance of L2BCommand. + */ + public L2BCommand() { + // Empty constructor + } + + /** + * Executes the long64 to byte8 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long value = (long) operandStack.pop(); + byte convertedValue = (byte) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java new file mode 100644 index 0000000..54652d6 --- /dev/null +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/L2SCommand.java @@ -0,0 +1,48 @@ +package org.jcnc.snow.vm.commands.type.conversion; + +import org.jcnc.snow.vm.interfaces.Command; +import org.jcnc.snow.vm.module.CallStack; +import org.jcnc.snow.vm.module.LocalVariableStore; +import org.jcnc.snow.vm.module.OperandStack; + +/** + * L2SCommand Opcode: Represents the type conversion operation from long64 to short16 in the virtual machine. + *

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

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a short16 value.
  4. + *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a short16 type for high-precision floating-point computations.

+ */ +public class L2SCommand implements Command { + + /** + * Default constructor for creating an instance of L2SCommand. + */ + public L2SCommand() { + // Empty constructor + } + + /** + * Executes the long64 to short16 conversion operation. + * + * @param parts The array of instruction parameters, which is not used in this operation. + * @param currentPC The current program counter, representing the instruction address. + * @param operandStack The operand stack of the virtual machine. + * @param localVariableStore The local variable store for managing method-local variables. + * @param callStack The call stack of the virtual machine. + * @return The updated program counter after execution. + */ + @Override + public int execute(String[] parts, int currentPC, OperandStack operandStack, + LocalVariableStore localVariableStore, CallStack callStack) { + long value = (long) operandStack.pop(); + short convertedValue = (short) value; + operandStack.push(convertedValue); + return currentPC + 1; + } +} From 872865268b2db68422c0bfc3d8ccb91ae4ca4d65 Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:07:07 +0800 Subject: [PATCH 22/62] =?UTF-8?q?docs:=20=E4=BF=AE=E6=94=B9=E6=8B=BC?= =?UTF-8?q?=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java | 4 ++-- .../org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java | 4 ++-- .../org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java index ab11cf0..41a8cec 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/D2SCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top double64 value from the operand stack.
  2. - *
  3. Convert the double64 value to an short16 value (this may involve truncation).
  4. + *
  5. Convert the double64 value to a short16 value (this may involve truncation).
  6. *
  7. Push the converted short16 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to narrow a double64 value to an short16 type for further integer-based operations.

+ *

This opcode is used to narrow a double64 value to a short16 type for further integer-based operations.

*/ public class D2SCommand implements Command { diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java index 2f3381f..7703f26 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2DCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an double64 value.
  4. + *
  5. Convert the short16 value to a double64 value.
  6. *
  7. Push the converted double64 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to widen a short16 value to an double64 type, facilitating subsequent integer arithmetic or comparison operations.

+ *

This opcode is used to widen a short16 value to a double64 type, facilitating subsequent integer arithmetic or comparison operations.

*/ public class S2DCommand implements Command { diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java index 78fbb4a..478e397 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2FCommand.java @@ -12,11 +12,11 @@ import org.jcnc.snow.vm.module.OperandStack; *

Execution Steps:

*
    *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an float32 value.
  4. + *
  5. Convert the short16 value to a float32 value.
  6. *
  7. Push the converted float32 value back onto the operand stack for subsequent operations.
  8. *
* - *

This opcode is used to widen a short16 value to an float32 type, facilitating subsequent integer arithmetic or comparison operations.

+ *

This opcode is used to widen a short16 value to a float32 type, facilitating subsequent integer arithmetic or comparison operations.

*/ public class S2FCommand implements Command { From f382b2bc5455f680867e49235793e1bb8fce755c Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Sat, 28 Jun 2025 21:08:49 +0800 Subject: [PATCH 23/62] =?UTF-8?q?style:=20=E7=BB=9F=E4=B8=80=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java index fa86e5f..d94eb8a 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/conversion/S2BCommand.java @@ -40,7 +40,8 @@ public class S2BCommand implements Command { @Override public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) { - byte convertedValue = (byte) ((short) operandStack.pop()); + short value = (short) operandStack.pop(); + byte convertedValue = (byte) value; operandStack.push(convertedValue); return currentPC + 1; } From 4f63f88b400de03baf0e47f09e5fb608960068dc Mon Sep 17 00:00:00 2001 From: zhangxun <1958638841@qq.com> Date: Tue, 8 Jul 2025 20:19:45 +0800 Subject: [PATCH 24/62] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E6=95=B0=E5=80=BC=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/snow/vm/engine/VMOpCode.java | 200 ++++++++++-------- .../snow/vm/factories/CommandFactory.java | 29 ++- 2 files changed, 135 insertions(+), 94 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 c53f511..8b634ca 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java @@ -2043,34 +2043,33 @@ public class VMOpCode { // endregion // region Type Conversion (0x00C0-0x00DF) - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a long64 value.
  4. - *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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

- */ - public static final int I2L = 0x00C0; - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a short16 value (this may involve truncation).
  4. - *
  5. Push the converted short16 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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 = 0x00C1; + // region Byte8 (0x00C0-0xC4) + + public static final int B2S = 0x00C0; + + public static final int B2I = 0x00C1; + + public static final int B2L = 0x00C2; + + public static final int B2F = 0x00C3; + + public static final int B2D = 0x00C4; + // endregion Byte8 + + // region Short16 (0x00C5-0xC9) + + public static final int S2B = 0x00C5; + + public static final int S2I = 0x00C6; + + public static final int S2L = 0x00C7; + + public static final int S2F = 0x00C8; + + public static final int S2D = 0x00C9; + // endregion Short16 + + // region Int32 (0x00CA-0xCE) /** * I2B Opcode: Represents the type conversion operation from int32 to byte8 in the virtual machine. *

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

@@ -2084,21 +2083,37 @@ 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 = 0x00C2; + public static final int I2B = 0x00CA; + /** - * 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.

+ * 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.

* *

Execution Steps:

*
    *
  1. Pop the top int32 value from the operand stack.
  2. - *
  3. Convert the int32 value to a double64 value.
  4. - *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
  7. Convert the int32 value to a short16 value (this may involve truncation).
  8. + *
  9. Push the converted short16 value back onto the operand stack for subsequent operations.
  10. *
* - *

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

+ *

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 I2D = 0x00C3; + public static final int I2S = 0x00CB; + + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top int32 value from the operand stack.
  2. + *
  3. Convert the int32 value to a long64 value.
  4. + *
  5. Push the converted long64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ + public static final int I2L = 0x00CC; /** * 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.

@@ -2112,7 +2127,29 @@ 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 = 0x00C4; + public static final int I2F = 0x00CD; + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top int32 value from the operand stack.
  2. + *
  3. Convert the int32 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

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

+ */ + public static final int I2D = 0x00CE; + // endregion Int32 + + // region Long64 (0x00CF-0xD3) + + public static final int L2B = 0x00CF; + + public static final int L2S = 0x00D0; + /** * 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.

@@ -2126,21 +2163,7 @@ 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 = 0x00C5; - /** - * 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.

- * - *

Execution Steps:

- *
    - *
  1. Pop the top long64 value from the operand stack.
  2. - *
  3. Convert the long64 value to a double64 value.
  4. - *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.

- */ - public static final int L2D = 0x00C6; + public static final int L2I = 0x00D1; /** * L2F Opcode: Represents the type conversion operation from long64 to float32 in the virtual machine. *

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

@@ -2154,7 +2177,29 @@ public class VMOpCode { * *

This opcode is used to convert a long64 value to a float32 type, typically for floating-point arithmetic involving long values.

*/ - public static final int L2F = 0x00C7; + public static final int L2F = 0x00D2; + /** + * 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.

+ * + *

Execution Steps:

+ *
    + *
  1. Pop the top long64 value from the operand stack.
  2. + *
  3. Convert the long64 value to a double64 value.
  4. + *
  5. Push the converted double64 value back onto the operand stack for subsequent operations.
  6. + *
+ * + *

This opcode is used to widen a long64 value to a double64 type for high-precision floating-point computations.

+ */ + public static final int L2D = 0x00D3; + // endregion Long64 + + // region Float32 (0x00D4-0xD8) + + public static final int F2B = 0x00D4; + + public static final int F2S = 0x00D5; + /** * F2I Opcode: Represents the type conversion operation from float32 to int32 in the virtual machine. *

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

@@ -2168,7 +2213,7 @@ public class VMOpCode { * *

This opcode is used to convert a float32 value to an int32 type for further integer-based operations or comparisons.

*/ - public static final int F2I = 0x00C8; + public static final int F2I = 0x00D6; /** * F2L Opcode: Represents the type conversion operation from float32 to long64 in the virtual machine. *

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

@@ -2182,7 +2227,7 @@ public class VMOpCode { * *

This opcode is used to widen a float32 value to a long64 type, which is useful when operations require a larger numeric range.

*/ - public static final int F2L = 0x00C9; + public static final int F2L = 0x00D7; /** * F2D Opcode: Represents the type conversion operation from float32 to double64 in the virtual machine. *

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

@@ -2196,7 +2241,15 @@ public class VMOpCode { * *

This opcode is used to promote a float32 value to a double64 type, thereby increasing precision for floating-point computations.

*/ - public static final int F2D = 0x00CA; + public static final int F2D = 0x00D8; + // endregion Float32 + + // region Double64 (0x00D9-0xDD) + + public static final int D2B = 0x00D9; + + public static final int D2S = 0x00DA; + /** * D2I Opcode: Represents the type conversion operation from double64 to int32 in the virtual machine. *

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

@@ -2210,7 +2263,7 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to an int32 type for further integer-based processing.

*/ - public static final int D2I = 0x00CB; + public static final int D2I = 0x00DB; /** * D2L Opcode: Represents the type conversion operation from double64 to long64 in the virtual machine. *

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

@@ -2224,7 +2277,7 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to a long64 type, which can then be used for integer operations.

*/ - public static final int D2L = 0x00CC; + public static final int D2L = 0x00DC; /** * D2F Opcode: Represents the type conversion operation from double64 to float32 in the virtual machine. *

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

@@ -2238,36 +2291,9 @@ public class VMOpCode { * *

This opcode is used to narrow a double64 value to a float32 type when lower precision floating-point arithmetic is acceptable.

*/ - public static final int D2F = 0x00CD; - /** - * S2I Opcode: Represents the type conversion operation from short16 to int32 in the virtual machine. - *

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

- * - *

Execution Steps:

- *
    - *
  1. Pop the top short16 value from the operand stack.
  2. - *
  3. Convert the short16 value to an int32 value.
  4. - *
  5. Push the converted int32 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

This opcode is used to widen a short16 value to an int32 type, facilitating subsequent integer arithmetic or comparison operations.

- */ - public static final int S2I = 0x00CE; - /** - * B2I Opcode: Represents the type conversion operation from byte8 to int32 in the virtual machine. - *

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

- * - *

Execution Steps:

- *
    - *
  1. Pop the top byte8 value from the operand stack.
  2. - *
  3. Convert the byte8 value to an int32 value.
  4. - *
  5. Push the converted int32 value back onto the operand stack for subsequent operations.
  6. - *
- * - *

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 = 0x00CF; - // endregion + public static final int D2F = 0x00DD; + // endregion Double64 + // endregion Conversion // region Stack Control (0x0100-0x01FF) /** diff --git a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java index a5af00b..4054a11 100644 --- a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java +++ b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java @@ -207,26 +207,41 @@ public class CommandFactory { // endregion // region Type Conversion (0x00C0-0x00DF) - COMMANDS[VMOpCode.I2L] = new I2LCommand(); - COMMANDS[VMOpCode.I2S] = new I2SCommand(); + COMMANDS[VMOpCode.B2S] = new B2SCommand(); + COMMANDS[VMOpCode.B2I] = new B2ICommand(); + COMMANDS[VMOpCode.B2L] = new B2LCommand(); + COMMANDS[VMOpCode.B2F] = new B2FCommand(); + COMMANDS[VMOpCode.B2D] = new B2DCommand(); + + COMMANDS[VMOpCode.S2B] = new S2BCommand(); + COMMANDS[VMOpCode.S2I] = new S2ICommand(); + COMMANDS[VMOpCode.S2L] = new S2LCommand(); + COMMANDS[VMOpCode.S2F] = new S2FCommand(); + COMMANDS[VMOpCode.S2D] = new S2DCommand(); + COMMANDS[VMOpCode.I2B] = new I2BCommand(); - COMMANDS[VMOpCode.I2D] = new I2DCommand(); + COMMANDS[VMOpCode.I2S] = new I2SCommand(); + COMMANDS[VMOpCode.I2L] = new I2LCommand(); COMMANDS[VMOpCode.I2F] = new I2FCommand(); + COMMANDS[VMOpCode.I2D] = new I2DCommand(); + COMMANDS[VMOpCode.L2B] = new L2BCommand(); + COMMANDS[VMOpCode.L2S] = new L2SCommand(); COMMANDS[VMOpCode.L2I] = new L2ICommand(); - COMMANDS[VMOpCode.L2D] = new L2DCommand(); COMMANDS[VMOpCode.L2F] = new L2FCommand(); + COMMANDS[VMOpCode.L2D] = new L2DCommand(); + COMMANDS[VMOpCode.F2B] = new F2BCommand(); + COMMANDS[VMOpCode.F2S] = new F2SCommand(); COMMANDS[VMOpCode.F2I] = new F2ICommand(); COMMANDS[VMOpCode.F2L] = new F2LCommand(); COMMANDS[VMOpCode.F2D] = new F2DCommand(); + COMMANDS[VMOpCode.D2B] = new D2BCommand(); + COMMANDS[VMOpCode.D2S] = new D2SCommand(); COMMANDS[VMOpCode.D2I] = new D2ICommand(); COMMANDS[VMOpCode.D2L] = new D2LCommand(); COMMANDS[VMOpCode.D2F] = new D2FCommand(); - - COMMANDS[VMOpCode.S2I] = new S2ICommand(); - COMMANDS[VMOpCode.B2I] = new B2ICommand(); // endregion // region Stack Control (0x0100-0x01FF) From 43aa055d7d193aaaaaab3bc2dfe77ef767b510ee Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 10 Jul 2025 11:34:31 +0800 Subject: [PATCH 25/62] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=20Demo12=20?= =?UTF-8?q?=E4=B8=BB=E7=A8=8B=E5=BA=8F=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建 Main.snow 文件,实现了一个简单的主程序 - 包含两个函数:main 和 foo - main函数中调用了 foo 函数- foo 函数中包含一个无效的 if 语句,始终返回 0 --- playground/Demo12/Main.snow | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 playground/Demo12/Main.snow diff --git a/playground/Demo12/Main.snow b/playground/Demo12/Main.snow new file mode 100644 index 0000000..134096c --- /dev/null +++ b/playground/Demo12/Main.snow @@ -0,0 +1,21 @@ +module: Main + function: main + return_type: int + body: + foo() + + return 0 + end body + end function + + function: foo + return_type: int + body: + if false then + return 1 + end if + + return 0 + end body + end function +end module \ No newline at end of file From e1f36d96896f32743296a4a44e0f12a08e27e5d7 Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 10 Jul 2025 11:45:05 +0800 Subject: [PATCH 26/62] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=20Demo=20?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E9=85=8D=E7=BD=AE=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改了多个 Demo 运行配置文件中的程序参数,将示例代码路径从根目录下的 playground 子目录移动到 playground/Demo 子目录- 新增 Demo12 运行配置文件,使用更新后的路径格式 --- .run/Demo1.run.xml | 2 +- .run/Demo10.run.xml | 4 ++-- .run/Demo12.run.xml | 17 +++++++++++++++++ .run/Demo2.run.xml | 4 ++-- .run/Demo3.run.xml | 4 ++-- .run/Demo4.run.xml | 4 ++-- .run/Demo5.run.xml | 4 ++-- .run/Demo6.run.xml | 4 ++-- .run/Demo7.run.xml | 4 ++-- .run/Demo8.run.xml | 4 ++-- .run/Demo9.run.xml | 4 ++-- 11 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 .run/Demo12.run.xml diff --git a/.run/Demo1.run.xml b/.run/Demo1.run.xml index 653910c..055866b 100644 --- a/.run/Demo1.run.xml +++ b/.run/Demo1.run.xml @@ -3,7 +3,7 @@