From 6acfac396087dab8d4a59db411f058dc933a04b0 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 6 Sep 2025 14:54:27 +0800 Subject: [PATCH 01/19] =?UTF-8?q?refactor:=20=E5=88=A0=E9=99=A4=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E5=AF=BC=E5=85=A5=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snow/vm/factories/CommandFactory.java | 292 ++++++++---------- 1 file changed, 132 insertions(+), 160 deletions(-) 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 fc4a3edd..a9bc7a32 100644 --- a/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java +++ b/src/main/java/org/jcnc/snow/vm/factories/CommandFactory.java @@ -1,54 +1,24 @@ package org.jcnc.snow.vm.factories; -import org.jcnc.snow.vm.commands.system.control.SyscallCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.*; -import org.jcnc.snow.vm.commands.type.control.double64.*; -import org.jcnc.snow.vm.commands.type.control.float32.*; -import org.jcnc.snow.vm.commands.type.control.int32.*; -import org.jcnc.snow.vm.commands.type.control.long64.*; +import org.jcnc.snow.vm.commands.flow.control.CallCommand; +import org.jcnc.snow.vm.commands.flow.control.JumpCommand; +import org.jcnc.snow.vm.commands.flow.control.RetCommand; import org.jcnc.snow.vm.commands.ref.control.RLoadCommand; import org.jcnc.snow.vm.commands.ref.control.RPushCommand; import org.jcnc.snow.vm.commands.ref.control.RStoreCommand; -import org.jcnc.snow.vm.commands.type.control.short16.*; -import org.jcnc.snow.vm.commands.type.control.byte8.BAndCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BOrCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BXorCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IAndCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IOrCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IXorCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LAndCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LOrCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LXorCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SAndCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SOrCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SXorCommand; -import org.jcnc.snow.vm.commands.flow.control.JumpCommand; -import org.jcnc.snow.vm.commands.flow.control.CallCommand; -import org.jcnc.snow.vm.commands.flow.control.RetCommand; import org.jcnc.snow.vm.commands.register.control.MovCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BLoadCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BStoreCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DLoadCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DStoreCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FLoadCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FStoreCommand; -import org.jcnc.snow.vm.commands.type.control.int32.ILoadCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IStoreCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LLoadCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LStoreCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SLoadCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SStoreCommand; import org.jcnc.snow.vm.commands.stack.control.DupCommand; import org.jcnc.snow.vm.commands.stack.control.PopCommand; import org.jcnc.snow.vm.commands.stack.control.SwapCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BPushCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DPushCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FPushCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IPushCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LPushCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SPushCommand; -import org.jcnc.snow.vm.commands.type.conversion.*; import org.jcnc.snow.vm.commands.system.control.HaltCommand; +import org.jcnc.snow.vm.commands.system.control.SyscallCommand; +import org.jcnc.snow.vm.commands.type.control.byte8.*; +import org.jcnc.snow.vm.commands.type.control.double64.*; +import org.jcnc.snow.vm.commands.type.control.float32.*; +import org.jcnc.snow.vm.commands.type.control.int32.*; +import org.jcnc.snow.vm.commands.type.control.long64.*; +import org.jcnc.snow.vm.commands.type.control.short16.*; +import org.jcnc.snow.vm.commands.type.conversion.*; import org.jcnc.snow.vm.engine.VMOpCode; import org.jcnc.snow.vm.interfaces.Command; @@ -60,7 +30,9 @@ import java.util.Optional; *

This class uses an array for fast, constant-time access to corresponding command instances.

*/ public class CommandFactory { - /** Complete command table. 0x0000 – 0x04FF (inclusive). */ + /** + * Complete command table. 0x0000 – 0x04FF (inclusive). + */ private static final Command[] COMMANDS = new Command[0x0500]; static { @@ -68,146 +40,146 @@ public class CommandFactory { // region Type Control (0x0000-0x00BF) // region Byte8 (0x0000-0x001F) - COMMANDS[VMOpCode.B_ADD] = new BAddCommand(); - COMMANDS[VMOpCode.B_SUB] = new BSubCommand(); - COMMANDS[VMOpCode.B_MUL] = new BMulCommand(); - COMMANDS[VMOpCode.B_DIV] = new BDivCommand(); - COMMANDS[VMOpCode.B_MOD] = new BModCommand(); - COMMANDS[VMOpCode.B_NEG] = new BNegCommand(); - COMMANDS[VMOpCode.B_INC] = new BIncCommand(); - - COMMANDS[VMOpCode.B_AND] = new BAndCommand(); - COMMANDS[VMOpCode.B_OR] = new BOrCommand(); - COMMANDS[VMOpCode.B_XOR] = new BXorCommand(); - - COMMANDS[VMOpCode.B_PUSH] = new BPushCommand(); - COMMANDS[VMOpCode.B_LOAD] = new BLoadCommand(); + COMMANDS[VMOpCode.B_ADD] = new BAddCommand(); + COMMANDS[VMOpCode.B_SUB] = new BSubCommand(); + COMMANDS[VMOpCode.B_MUL] = new BMulCommand(); + COMMANDS[VMOpCode.B_DIV] = new BDivCommand(); + COMMANDS[VMOpCode.B_MOD] = new BModCommand(); + COMMANDS[VMOpCode.B_NEG] = new BNegCommand(); + COMMANDS[VMOpCode.B_INC] = new BIncCommand(); + + COMMANDS[VMOpCode.B_AND] = new BAndCommand(); + COMMANDS[VMOpCode.B_OR] = new BOrCommand(); + COMMANDS[VMOpCode.B_XOR] = new BXorCommand(); + + COMMANDS[VMOpCode.B_PUSH] = new BPushCommand(); + COMMANDS[VMOpCode.B_LOAD] = new BLoadCommand(); COMMANDS[VMOpCode.B_STORE] = new BStoreCommand(); - COMMANDS[VMOpCode.B_CE] = new BCECommand(); - COMMANDS[VMOpCode.B_CNE] = new BCNECommand(); - COMMANDS[VMOpCode.B_CG] = new BCGCommand(); - COMMANDS[VMOpCode.B_CGE] = new BCGECommand(); - COMMANDS[VMOpCode.B_CL] = new BCLCommand(); - COMMANDS[VMOpCode.B_CLE] = new BCLECommand(); + COMMANDS[VMOpCode.B_CE] = new BCECommand(); + COMMANDS[VMOpCode.B_CNE] = new BCNECommand(); + COMMANDS[VMOpCode.B_CG] = new BCGCommand(); + COMMANDS[VMOpCode.B_CGE] = new BCGECommand(); + COMMANDS[VMOpCode.B_CL] = new BCLCommand(); + COMMANDS[VMOpCode.B_CLE] = new BCLECommand(); // endregion // region Short16 (0x0020-0x003F) - COMMANDS[VMOpCode.S_ADD] = new SAddCommand(); - COMMANDS[VMOpCode.S_SUB] = new SSubCommand(); - COMMANDS[VMOpCode.S_MUL] = new SMulCommand(); - COMMANDS[VMOpCode.S_DIV] = new SDivCommand(); - COMMANDS[VMOpCode.S_MOD] = new SModCommand(); - COMMANDS[VMOpCode.S_NEG] = new SNegCommand(); - COMMANDS[VMOpCode.S_INC] = new SIncCommand(); - - COMMANDS[VMOpCode.S_AND] = new SAndCommand(); - COMMANDS[VMOpCode.S_OR] = new SOrCommand(); - COMMANDS[VMOpCode.S_XOR] = new SXorCommand(); - - COMMANDS[VMOpCode.S_PUSH] = new SPushCommand(); - COMMANDS[VMOpCode.S_LOAD] = new SLoadCommand(); + COMMANDS[VMOpCode.S_ADD] = new SAddCommand(); + COMMANDS[VMOpCode.S_SUB] = new SSubCommand(); + COMMANDS[VMOpCode.S_MUL] = new SMulCommand(); + COMMANDS[VMOpCode.S_DIV] = new SDivCommand(); + COMMANDS[VMOpCode.S_MOD] = new SModCommand(); + COMMANDS[VMOpCode.S_NEG] = new SNegCommand(); + COMMANDS[VMOpCode.S_INC] = new SIncCommand(); + + COMMANDS[VMOpCode.S_AND] = new SAndCommand(); + COMMANDS[VMOpCode.S_OR] = new SOrCommand(); + COMMANDS[VMOpCode.S_XOR] = new SXorCommand(); + + COMMANDS[VMOpCode.S_PUSH] = new SPushCommand(); + COMMANDS[VMOpCode.S_LOAD] = new SLoadCommand(); COMMANDS[VMOpCode.S_STORE] = new SStoreCommand(); - COMMANDS[VMOpCode.S_CE] = new SCECommand(); - COMMANDS[VMOpCode.S_CNE] = new SCNECommand(); - COMMANDS[VMOpCode.S_CG] = new SCGCommand(); - COMMANDS[VMOpCode.S_CGE] = new SCGECommand(); - COMMANDS[VMOpCode.S_CL] = new SCLCommand(); - COMMANDS[VMOpCode.S_CLE] = new SCLECommand(); + COMMANDS[VMOpCode.S_CE] = new SCECommand(); + COMMANDS[VMOpCode.S_CNE] = new SCNECommand(); + COMMANDS[VMOpCode.S_CG] = new SCGCommand(); + COMMANDS[VMOpCode.S_CGE] = new SCGECommand(); + COMMANDS[VMOpCode.S_CL] = new SCLCommand(); + COMMANDS[VMOpCode.S_CLE] = new SCLECommand(); // endregion // region Int32 (0x0040-0x005F) - COMMANDS[VMOpCode.I_ADD] = new IAddCommand(); - COMMANDS[VMOpCode.I_SUB] = new ISubCommand(); - COMMANDS[VMOpCode.I_MUL] = new IMulCommand(); - COMMANDS[VMOpCode.I_DIV] = new IDivCommand(); - COMMANDS[VMOpCode.I_MOD] = new IModCommand(); - COMMANDS[VMOpCode.I_NEG] = new INegCommand(); - COMMANDS[VMOpCode.I_INC] = new IIncCommand(); - - COMMANDS[VMOpCode.I_AND] = new IAndCommand(); - COMMANDS[VMOpCode.I_OR] = new IOrCommand(); - COMMANDS[VMOpCode.I_XOR] = new IXorCommand(); - - COMMANDS[VMOpCode.I_PUSH] = new IPushCommand(); - COMMANDS[VMOpCode.I_LOAD] = new ILoadCommand(); + COMMANDS[VMOpCode.I_ADD] = new IAddCommand(); + COMMANDS[VMOpCode.I_SUB] = new ISubCommand(); + COMMANDS[VMOpCode.I_MUL] = new IMulCommand(); + COMMANDS[VMOpCode.I_DIV] = new IDivCommand(); + COMMANDS[VMOpCode.I_MOD] = new IModCommand(); + COMMANDS[VMOpCode.I_NEG] = new INegCommand(); + COMMANDS[VMOpCode.I_INC] = new IIncCommand(); + + COMMANDS[VMOpCode.I_AND] = new IAndCommand(); + COMMANDS[VMOpCode.I_OR] = new IOrCommand(); + COMMANDS[VMOpCode.I_XOR] = new IXorCommand(); + + COMMANDS[VMOpCode.I_PUSH] = new IPushCommand(); + COMMANDS[VMOpCode.I_LOAD] = new ILoadCommand(); COMMANDS[VMOpCode.I_STORE] = new IStoreCommand(); - COMMANDS[VMOpCode.I_CE] = new ICECommand(); - COMMANDS[VMOpCode.I_CNE] = new ICNECommand(); - COMMANDS[VMOpCode.I_CG] = new ICGCommand(); - COMMANDS[VMOpCode.I_CGE] = new ICGECommand(); - COMMANDS[VMOpCode.I_CL] = new ICLCommand(); - COMMANDS[VMOpCode.I_CLE] = new ICLECommand(); + COMMANDS[VMOpCode.I_CE] = new ICECommand(); + COMMANDS[VMOpCode.I_CNE] = new ICNECommand(); + COMMANDS[VMOpCode.I_CG] = new ICGCommand(); + COMMANDS[VMOpCode.I_CGE] = new ICGECommand(); + COMMANDS[VMOpCode.I_CL] = new ICLCommand(); + COMMANDS[VMOpCode.I_CLE] = new ICLECommand(); // endregion // region Long64 (0x0060-0x007F) - COMMANDS[VMOpCode.L_ADD] = new LAddCommand(); - COMMANDS[VMOpCode.L_SUB] = new LSubCommand(); - COMMANDS[VMOpCode.L_MUL] = new LMulCommand(); - COMMANDS[VMOpCode.L_DIV] = new LDivCommand(); - COMMANDS[VMOpCode.L_MOD] = new LModCommand(); - COMMANDS[VMOpCode.L_NEG] = new LNegCommand(); - COMMANDS[VMOpCode.L_INC] = new LIncCommand(); - - COMMANDS[VMOpCode.L_AND] = new LAndCommand(); - COMMANDS[VMOpCode.L_OR] = new LOrCommand(); - COMMANDS[VMOpCode.L_XOR] = new LXorCommand(); - - COMMANDS[VMOpCode.L_PUSH] = new LPushCommand(); - COMMANDS[VMOpCode.L_LOAD] = new LLoadCommand(); + COMMANDS[VMOpCode.L_ADD] = new LAddCommand(); + COMMANDS[VMOpCode.L_SUB] = new LSubCommand(); + COMMANDS[VMOpCode.L_MUL] = new LMulCommand(); + COMMANDS[VMOpCode.L_DIV] = new LDivCommand(); + COMMANDS[VMOpCode.L_MOD] = new LModCommand(); + COMMANDS[VMOpCode.L_NEG] = new LNegCommand(); + COMMANDS[VMOpCode.L_INC] = new LIncCommand(); + + COMMANDS[VMOpCode.L_AND] = new LAndCommand(); + COMMANDS[VMOpCode.L_OR] = new LOrCommand(); + COMMANDS[VMOpCode.L_XOR] = new LXorCommand(); + + COMMANDS[VMOpCode.L_PUSH] = new LPushCommand(); + COMMANDS[VMOpCode.L_LOAD] = new LLoadCommand(); COMMANDS[VMOpCode.L_STORE] = new LStoreCommand(); - COMMANDS[VMOpCode.L_CE] = new LCECommand(); - COMMANDS[VMOpCode.L_CNE] = new LCNECommand(); - COMMANDS[VMOpCode.L_CG] = new LCGCommand(); - COMMANDS[VMOpCode.L_CGE] = new LCGECommand(); - COMMANDS[VMOpCode.L_CL] = new LCLCommand(); - COMMANDS[VMOpCode.L_CLE] = new LCLECommand(); + COMMANDS[VMOpCode.L_CE] = new LCECommand(); + COMMANDS[VMOpCode.L_CNE] = new LCNECommand(); + COMMANDS[VMOpCode.L_CG] = new LCGCommand(); + COMMANDS[VMOpCode.L_CGE] = new LCGECommand(); + COMMANDS[VMOpCode.L_CL] = new LCLCommand(); + COMMANDS[VMOpCode.L_CLE] = new LCLECommand(); // endregion // region Float32 (0x0080-0x009F) - COMMANDS[VMOpCode.F_ADD] = new FAddCommand(); - COMMANDS[VMOpCode.F_SUB] = new FSubCommand(); - COMMANDS[VMOpCode.F_MUL] = new FMulCommand(); - COMMANDS[VMOpCode.F_DIV] = new FDivCommand(); - COMMANDS[VMOpCode.F_MOD] = new FModCommand(); - COMMANDS[VMOpCode.F_NEG] = new FNegCommand(); - COMMANDS[VMOpCode.F_INC] = new FIncCommand(); - - COMMANDS[VMOpCode.F_PUSH] = new FPushCommand(); - COMMANDS[VMOpCode.F_LOAD] = new FLoadCommand(); + COMMANDS[VMOpCode.F_ADD] = new FAddCommand(); + COMMANDS[VMOpCode.F_SUB] = new FSubCommand(); + COMMANDS[VMOpCode.F_MUL] = new FMulCommand(); + COMMANDS[VMOpCode.F_DIV] = new FDivCommand(); + COMMANDS[VMOpCode.F_MOD] = new FModCommand(); + COMMANDS[VMOpCode.F_NEG] = new FNegCommand(); + COMMANDS[VMOpCode.F_INC] = new FIncCommand(); + + COMMANDS[VMOpCode.F_PUSH] = new FPushCommand(); + COMMANDS[VMOpCode.F_LOAD] = new FLoadCommand(); COMMANDS[VMOpCode.F_STORE] = new FStoreCommand(); - COMMANDS[VMOpCode.F_CE] = new FCECommand(); - COMMANDS[VMOpCode.F_CNE] = new FCNECommand(); - COMMANDS[VMOpCode.F_CG] = new FCGCommand(); - COMMANDS[VMOpCode.F_CGE] = new FCGECommand(); - COMMANDS[VMOpCode.F_CL] = new FCLCommand(); - COMMANDS[VMOpCode.F_CLE] = new FCLECommand(); + COMMANDS[VMOpCode.F_CE] = new FCECommand(); + COMMANDS[VMOpCode.F_CNE] = new FCNECommand(); + COMMANDS[VMOpCode.F_CG] = new FCGCommand(); + COMMANDS[VMOpCode.F_CGE] = new FCGECommand(); + COMMANDS[VMOpCode.F_CL] = new FCLCommand(); + COMMANDS[VMOpCode.F_CLE] = new FCLECommand(); // endregion // region Double64 (0x00A0-0x00BF) - COMMANDS[VMOpCode.D_ADD] = new DAddCommand(); - COMMANDS[VMOpCode.D_SUB] = new DSubCommand(); - COMMANDS[VMOpCode.D_MUL] = new DMulCommand(); - COMMANDS[VMOpCode.D_DIV] = new DDivCommand(); - COMMANDS[VMOpCode.D_MOD] = new DModCommand(); - COMMANDS[VMOpCode.D_NEG] = new DNegCommand(); - COMMANDS[VMOpCode.D_INC] = new DIncCommand(); - - COMMANDS[VMOpCode.D_PUSH] = new DPushCommand(); - COMMANDS[VMOpCode.D_LOAD] = new DLoadCommand(); + COMMANDS[VMOpCode.D_ADD] = new DAddCommand(); + COMMANDS[VMOpCode.D_SUB] = new DSubCommand(); + COMMANDS[VMOpCode.D_MUL] = new DMulCommand(); + COMMANDS[VMOpCode.D_DIV] = new DDivCommand(); + COMMANDS[VMOpCode.D_MOD] = new DModCommand(); + COMMANDS[VMOpCode.D_NEG] = new DNegCommand(); + COMMANDS[VMOpCode.D_INC] = new DIncCommand(); + + COMMANDS[VMOpCode.D_PUSH] = new DPushCommand(); + COMMANDS[VMOpCode.D_LOAD] = new DLoadCommand(); COMMANDS[VMOpCode.D_STORE] = new DStoreCommand(); - COMMANDS[VMOpCode.D_CE] = new DCECommand(); - COMMANDS[VMOpCode.D_CNE] = new DCNECommand(); - COMMANDS[VMOpCode.D_CG] = new DCGCommand(); - COMMANDS[VMOpCode.D_CGE] = new DCGECommand(); - COMMANDS[VMOpCode.D_CL] = new DCLCommand(); - COMMANDS[VMOpCode.D_CLE] = new DCLECommand(); + COMMANDS[VMOpCode.D_CE] = new DCECommand(); + COMMANDS[VMOpCode.D_CNE] = new DCNECommand(); + COMMANDS[VMOpCode.D_CG] = new DCGCommand(); + COMMANDS[VMOpCode.D_CGE] = new DCGECommand(); + COMMANDS[VMOpCode.D_CL] = new DCLCommand(); + COMMANDS[VMOpCode.D_CLE] = new DCLECommand(); // endregion // endregion @@ -257,24 +229,24 @@ public class CommandFactory { // endregion // region Stack Control (0x0100-0x01FF) - COMMANDS[VMOpCode.POP] = new PopCommand(); - COMMANDS[VMOpCode.DUP] = new DupCommand(); + COMMANDS[VMOpCode.POP] = new PopCommand(); + COMMANDS[VMOpCode.DUP] = new DupCommand(); COMMANDS[VMOpCode.SWAP] = new SwapCommand(); // endregion // region Flow Control (0x0200-0x02FF) COMMANDS[VMOpCode.JUMP] = new JumpCommand(); COMMANDS[VMOpCode.CALL] = new CallCommand(); - COMMANDS[VMOpCode.RET] = new RetCommand(); + COMMANDS[VMOpCode.RET] = new RetCommand(); // endregion // region Register Control (0x0300-0x03FF) - COMMANDS[VMOpCode.MOV] = new MovCommand(); + COMMANDS[VMOpCode.MOV] = new MovCommand(); // endregion // region System Control (0x0400-0x04FF) - COMMANDS[VMOpCode.HALT] = new HaltCommand(); - COMMANDS[VMOpCode.SYSCALL] = new SyscallCommand(); + COMMANDS[VMOpCode.HALT] = new HaltCommand(); + COMMANDS[VMOpCode.SYSCALL] = new SyscallCommand(); // COMMANDS[VMOpCode.DEBUG_TRAP] = new DebugTrapCommand(); // endregion -- Gitee From f8c019744cbb0dd4e265214ab8b1c5038e8a10d2 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 6 Sep 2025 16:23:35 +0800 Subject: [PATCH 02/19] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=20Demo34?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playground/Demo/Demo34/Main.snow | 9 +++++++++ playground/Demo/Demo34/OS.snow | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 playground/Demo/Demo34/Main.snow create mode 100644 playground/Demo/Demo34/OS.snow diff --git a/playground/Demo/Demo34/Main.snow b/playground/Demo/Demo34/Main.snow new file mode 100644 index 00000000..16e5cd9a --- /dev/null +++ b/playground/Demo/Demo34/Main.snow @@ -0,0 +1,9 @@ +module: Main + import:os + function: main + returns: void + body: + os.print(1) + end body + end function +end module \ No newline at end of file diff --git a/playground/Demo/Demo34/OS.snow b/playground/Demo/Demo34/OS.snow new file mode 100644 index 00000000..69dbb1ef --- /dev/null +++ b/playground/Demo/Demo34/OS.snow @@ -0,0 +1,18 @@ +module: os + function: print + params: + declare i1: int + returns: void + body: + syscall("PRINT", i1) + end body + end function + function: println + params: + declare i1: int + returns: void + body: + syscall("PRINTLN", i1) + end body + end function +end module \ No newline at end of file -- Gitee From c69e55336705f5ffd963acf823959752eb32e234 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 6 Sep 2025 16:24:15 +0800 Subject: [PATCH 03/19] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=20Demo34?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/Demo34.run.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .run/Demo34.run.xml diff --git a/.run/Demo34.run.xml b/.run/Demo34.run.xml new file mode 100644 index 00000000..d6e74c28 --- /dev/null +++ b/.run/Demo34.run.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file -- Gitee From aab5126734a4f78c8c7d2a1ef3a147ffdb823d63 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 6 Sep 2025 16:58:56 +0800 Subject: [PATCH 04/19] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=E5=AD=A6?= =?UTF-8?q?=E7=94=9F=E7=B1=BB=E5=92=8C=E4=BA=BA=E7=89=A9=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playground/Demo/Demo34/Main.snow | 13 +++++++++---- playground/Demo/Demo34/Person.snow | 20 ++++++++++++++++++++ playground/Demo/Demo34/Student.snow | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 playground/Demo/Demo34/Person.snow create mode 100644 playground/Demo/Demo34/Student.snow diff --git a/playground/Demo/Demo34/Main.snow b/playground/Demo/Demo34/Main.snow index 16e5cd9a..d681d77c 100644 --- a/playground/Demo/Demo34/Main.snow +++ b/playground/Demo/Demo34/Main.snow @@ -1,9 +1,14 @@ -module: Main - import:os +module: main + import: os,Student, Person + function: main returns: void body: - os.print(1) + declare a: Person = new Student(1) + + os.println(a.getName()) + + end body end function -end module \ No newline at end of file +end module \ No newline at end of file diff --git a/playground/Demo/Demo34/Person.snow b/playground/Demo/Demo34/Person.snow new file mode 100644 index 00000000..395cd06a --- /dev/null +++ b/playground/Demo/Demo34/Person.snow @@ -0,0 +1,20 @@ +module: Person +struct:Person + fields: + declare name: int + init: + params: + declare name: int + body: + this.name = name + end body + end init + + function: getName + returns: int + body: + return this.name + end body + end function +end struct +end module \ No newline at end of file diff --git a/playground/Demo/Demo34/Student.snow b/playground/Demo/Demo34/Student.snow new file mode 100644 index 00000000..a1cf41a4 --- /dev/null +++ b/playground/Demo/Demo34/Student.snow @@ -0,0 +1,24 @@ +module: Student +import : Person + +struct : Student extends Person + fields: + declare id: int + + init: + params: + declare name: int + body: + super(name) + end body + end init + + // 重写父类方法,演示多态 + function: getName + returns: int + body: + return super.getName() + 1000 + end body + end function +end struct +end module -- Gitee From 3c268b30233b5f06e8c2ee41b31d178aa96a8df4 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 8 Sep 2025 16:19:48 +0800 Subject: [PATCH 05/19] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=BC=E5=BC=8F=E5=92=8C=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整缩进和空格,提高代码可读性 - 重新排序导入语句,按照字母顺序排列 - 添加必要的注释,解释复杂逻辑和方法用途 - 移除未使用的变量和导入,清理冗余代码 --- src/main/java/org/jcnc/snow/cli/SnowCLI.java | 2 - .../jcnc/snow/cli/commands/InitCommand.java | 2 +- .../snow/cli/commands/InstallCommand.java | 2 +- .../snow/cli/commands/PublishCommand.java | 2 +- .../jcnc/snow/cli/commands/RunCommand.java | 2 +- .../snow/cli/commands/VersionCommand.java | 2 +- src/main/java/org/jcnc/snow/cli/doc/README.md | 12 +- .../backend/alloc/RegisterAllocator.java | 6 +- .../backend/builder/VMCodeGenerator.java | 1 + .../backend/core/InstructionGenerator.java | 8 +- .../jcnc/snow/compiler/backend/doc/README.md | 9 +- .../backend/generator/CmpJumpGenerator.java | 24 +- .../InstructionGeneratorProvider.java | 12 +- .../backend/generator/JumpGenerator.java | 2 +- .../backend/generator/UnaryOpGenerator.java | 10 +- .../backend/utils/TypePromoteUtils.java | 6 +- .../ir/builder/core/IRBuilderScope.java | 223 +++++++------ .../compiler/ir/builder/core/IRContext.java | 45 ++- .../ir/builder/core/IRProgramBuilder.java | 1 + .../ir/builder/handlers/UnaryHandler.java | 2 +- .../ir/builder/statement/FunctionBuilder.java | 12 +- .../builder/statement/handlers/IfHandler.java | 2 +- .../statement/handlers/LoopHandler.java | 2 +- .../statement/utils/ConditionalJump.java | 2 +- .../builder/statement/utils/ConstFolder.java | 1 - .../ir/builder/utils/IndexRefHelper.java | 2 +- .../compiler/ir/common/GlobalConstTable.java | 4 +- .../ir/common/GlobalFunctionTable.java | 2 +- .../snow/compiler/ir/core/IRFunction.java | 12 +- .../snow/compiler/ir/core/IRInstruction.java | 1 + .../org/jcnc/snow/compiler/ir/doc/README.md | 7 +- .../BinaryOperationInstruction.java | 22 +- .../ir/instruction/CallInstruction.java | 25 +- .../ir/instruction/IRAddInstruction.java | 12 +- .../instruction/IRCompareJumpInstruction.java | 24 +- .../ir/instruction/IRJumpInstruction.java | 4 +- .../ir/instruction/IRLabelInstruction.java | 4 +- .../ir/instruction/IRReturnInstruction.java | 4 +- .../ir/instruction/LoadConstInstruction.java | 8 +- .../ir/instruction/ReturnInstruction.java | 2 +- .../UnaryOperationInstruction.java | 14 +- .../compiler/ir/utils/ComparisonUtils.java | 41 ++- .../compiler/ir/utils/ExpressionUtils.java | 47 +-- .../compiler/ir/value/IRVirtualRegister.java | 4 +- .../compiler/lexer/core/LexerContext.java | 52 ++- .../snow/compiler/lexer/core/LexerEngine.java | 2 - .../compiler/lexer/core/LexicalException.java | 42 ++- .../lexer/scanners/AbstractTokenScanner.java | 2 +- .../lexer/scanners/SymbolTokenScanner.java | 2 +- .../lexer/scanners/UnknownTokenScanner.java | 4 +- .../jcnc/snow/compiler/lexer/token/Token.java | 40 ++- .../snow/compiler/lexer/token/TokenType.java | 128 ++++++-- .../compiler/lexer/utils/TokenPrinter.java | 2 +- .../compiler/parser/ast/AssignmentNode.java | 2 +- .../compiler/parser/ast/DeclarationNode.java | 18 +- .../parser/ast/ExpressionStatementNode.java | 2 +- .../jcnc/snow/compiler/parser/ast/IfNode.java | 2 +- .../snow/compiler/parser/ast/ImportNode.java | 2 +- .../parser/ast/IndexExpressionNode.java | 1 + .../parser/ast/MemberExpressionNode.java | 6 +- .../snow/compiler/parser/ast/ModuleNode.java | 12 +- .../parser/ast/NumberLiteralNode.java | 4 +- .../snow/compiler/parser/ast/ReturnNode.java | 12 +- .../parser/ast/StringLiteralNode.java | 4 +- .../snow/compiler/parser/ast/StructNode.java | 2 +- .../parser/ast/UnaryExpressionNode.java | 4 +- .../parser/ast/base/ExpressionNode.java | 3 +- .../snow/compiler/parser/ast/base/Node.java | 2 +- .../parser/ast/base/StatementNode.java | 3 +- .../compiler/parser/context/ParseError.java | 22 +- .../parser/context/ParseException.java | 20 +- .../expression/ArrayLiteralParselet.java | 24 +- .../expression/PrattExpressionParser.java | 24 +- .../parser/expression/Precedence.java | 36 ++- .../expression/StringLiteralParselet.java | 2 +- .../expression/UnaryOperatorParselet.java | 8 +- .../expression/base/ExpressionParser.java | 2 +- .../parser/expression/base/InfixParselet.java | 2 +- .../expression/base/PrefixParselet.java | 2 +- .../factory/StatementParserFactory.java | 18 +- .../parser/factory/TopLevelParserFactory.java | 14 +- .../compiler/parser/module/ImportParser.java | 2 +- .../statement/DeclarationStatementParser.java | 2 +- .../statement/ExpressionStatementParser.java | 2 +- .../parser/statement/IfStatementParser.java | 4 +- .../parser/statement/LoopStatementParser.java | 10 +- .../statement/ReturnStatementParser.java | 4 +- .../parser/statement/StatementParser.java | 2 +- .../parser/top/ScriptTopLevelParser.java | 2 +- .../parser/utils/FlexibleSectionParser.java | 4 +- .../compiler/parser/utils/JSONParser.java | 49 ++- .../compiler/parser/utils/JsonFormatter.java | 2 +- .../compiler/parser/utils/ParserUtils.java | 2 +- .../analyzers/base/ExpressionAnalyzer.java | 2 +- .../expression/BinaryExpressionAnalyzer.java | 4 +- .../expression/IdentifierAnalyzer.java | 4 +- .../expression/NewExpressionAnalyzer.java | 2 +- .../expression/StringLiteralAnalyzer.java | 2 +- .../expression/UnaryExpressionAnalyzer.java | 6 +- .../statement/AssignmentAnalyzer.java | 6 +- .../statement/DeclarationAnalyzer.java | 2 +- .../analyzers/statement/LoopAnalyzer.java | 2 +- .../analyzers/statement/ReturnAnalyzer.java | 2 +- .../semantic/core/BuiltinTypeRegistry.java | 21 +- .../semantic/core/SemanticAnalyzer.java | 16 +- .../semantic/core/SemanticAnalyzerRunner.java | 4 +- .../jcnc/snow/compiler/semantic/doc/README.md | 12 +- .../semantic/error/SemanticError.java | 2 +- .../snow/compiler/semantic/symbol/Symbol.java | 5 +- .../compiler/semantic/symbol/SymbolTable.java | 12 +- .../compiler/semantic/type/BuiltinType.java | 8 +- .../compiler/semantic/type/FunctionType.java | 10 +- .../snow/compiler/semantic/type/Type.java | 47 +-- .../utils/SemanticAnalysisReporter.java | 5 +- src/main/java/org/jcnc/snow/pkg/doc/README.md | 2 +- .../org/jcnc/snow/pkg/dsl/CloudDSLParser.java | 17 +- .../snow/pkg/lifecycle/LifecycleManager.java | 4 +- .../snow/pkg/lifecycle/LifecyclePhase.java | 24 +- .../snow/pkg/model/BuildConfiguration.java | 6 +- .../org/jcnc/snow/pkg/model/Dependency.java | 6 +- .../java/org/jcnc/snow/pkg/model/Project.java | 90 ++++-- .../snow/pkg/resolver/DependencyResolver.java | 4 +- .../org/jcnc/snow/pkg/tasks/CleanTask.java | 2 +- .../org/jcnc/snow/pkg/tasks/PackageTask.java | 4 +- .../org/jcnc/snow/pkg/tasks/PublishTask.java | 4 +- .../java/org/jcnc/snow/vm/VMInitializer.java | 2 +- .../vm/commands/flow/control/CallCommand.java | 3 +- .../vm/commands/flow/control/JumpCommand.java | 2 +- .../vm/commands/ref/control/RLoadCommand.java | 6 +- .../vm/commands/ref/control/RPushCommand.java | 303 +++++++++--------- .../commands/ref/control/RStoreCommand.java | 2 +- .../commands/system/control/HaltCommand.java | 2 +- .../type/control/byte8/BAddCommand.java | 2 +- .../type/control/byte8/BAndCommand.java | 2 +- .../type/control/byte8/BDivCommand.java | 2 +- .../type/control/byte8/BModCommand.java | 2 +- .../type/control/byte8/BMulCommand.java | 2 +- .../type/control/byte8/BOrCommand.java | 2 +- .../type/control/byte8/BSubCommand.java | 2 +- .../type/control/byte8/BXorCommand.java | 2 +- .../type/control/int32/ICECommand.java | 2 +- .../type/control/int32/ICGCommand.java | 2 +- .../type/control/int32/ICGECommand.java | 2 +- .../type/control/int32/ICLCommand.java | 2 +- .../type/control/int32/ICLECommand.java | 2 +- .../type/control/int32/ICNECommand.java | 2 +- .../type/control/short16/SAddCommand.java | 2 +- .../type/control/short16/SAndCommand.java | 2 +- .../type/control/short16/SDivCommand.java | 2 +- .../type/control/short16/SModCommand.java | 2 +- .../type/control/short16/SMulCommand.java | 2 +- .../type/control/short16/SOrCommand.java | 2 +- .../type/control/short16/SSubCommand.java | 2 +- .../type/control/short16/SXorCommand.java | 2 +- src/main/java/org/jcnc/snow/vm/doc/README.md | 15 +- .../org/jcnc/snow/vm/engine/VMOpCode.java | 170 +++++----- .../snow/vm/engine/VirtualMachineEngine.java | 32 +- .../jcnc/snow/vm/execution/CommandLoader.java | 3 +- .../java/org/jcnc/snow/vm/io/FDTable.java | 20 +- .../org/jcnc/snow/vm/module/CallStack.java | 1 + .../org/jcnc/snow/vm/module/Instance.java | 8 +- .../org/jcnc/snow/vm/module/StackFrame.java | 2 - .../org/jcnc/snow/vm/module/VirtualTable.java | 4 +- 163 files changed, 1313 insertions(+), 886 deletions(-) diff --git a/src/main/java/org/jcnc/snow/cli/SnowCLI.java b/src/main/java/org/jcnc/snow/cli/SnowCLI.java index d05b0bf7..0ce6ba0d 100644 --- a/src/main/java/org/jcnc/snow/cli/SnowCLI.java +++ b/src/main/java/org/jcnc/snow/cli/SnowCLI.java @@ -4,8 +4,6 @@ import org.jcnc.snow.cli.api.CLICommand; import org.jcnc.snow.cli.commands.*; import org.jcnc.snow.cli.utils.CLIUtils; import org.jcnc.snow.cli.utils.VersionUtils; -import org.jcnc.snow.common.Mode; -import org.jcnc.snow.common.SnowConfig; import java.util.Arrays; import java.util.Map; diff --git a/src/main/java/org/jcnc/snow/cli/commands/InitCommand.java b/src/main/java/org/jcnc/snow/cli/commands/InitCommand.java index 1986e2f8..fc62ffbd 100644 --- a/src/main/java/org/jcnc/snow/cli/commands/InitCommand.java +++ b/src/main/java/org/jcnc/snow/cli/commands/InitCommand.java @@ -14,7 +14,7 @@ import java.nio.file.Paths; *

* *
- * 用法示例: 
+ * 用法示例:
  * $ snow init
  * 
*/ diff --git a/src/main/java/org/jcnc/snow/cli/commands/InstallCommand.java b/src/main/java/org/jcnc/snow/cli/commands/InstallCommand.java index 09eb9b3c..ee47b440 100644 --- a/src/main/java/org/jcnc/snow/cli/commands/InstallCommand.java +++ b/src/main/java/org/jcnc/snow/cli/commands/InstallCommand.java @@ -14,7 +14,7 @@ import java.nio.file.Paths; *

* *
- * 用法示例: 
+ * 用法示例:
  * $ snow install
  * 
*/ diff --git a/src/main/java/org/jcnc/snow/cli/commands/PublishCommand.java b/src/main/java/org/jcnc/snow/cli/commands/PublishCommand.java index 347aeffc..4e8d5de2 100644 --- a/src/main/java/org/jcnc/snow/cli/commands/PublishCommand.java +++ b/src/main/java/org/jcnc/snow/cli/commands/PublishCommand.java @@ -17,7 +17,7 @@ import java.nio.file.Paths; *

* *
- * 用法示例: 
+ * 用法示例:
  * $ snow publish
  * 
*/ diff --git a/src/main/java/org/jcnc/snow/cli/commands/RunCommand.java b/src/main/java/org/jcnc/snow/cli/commands/RunCommand.java index 159dcb57..16c770ef 100644 --- a/src/main/java/org/jcnc/snow/cli/commands/RunCommand.java +++ b/src/main/java/org/jcnc/snow/cli/commands/RunCommand.java @@ -11,7 +11,7 @@ import org.jcnc.snow.pkg.tasks.RunTask; *

* *
- * 用法示例: 
+ * 用法示例:
  * $ snow run main.water
  * 
*/ diff --git a/src/main/java/org/jcnc/snow/cli/commands/VersionCommand.java b/src/main/java/org/jcnc/snow/cli/commands/VersionCommand.java index 94fc6e79..e12bec7c 100644 --- a/src/main/java/org/jcnc/snow/cli/commands/VersionCommand.java +++ b/src/main/java/org/jcnc/snow/cli/commands/VersionCommand.java @@ -10,7 +10,7 @@ import org.jcnc.snow.cli.api.CLICommand; *

* *
- * 用法示例: 
+ * 用法示例:
  * $ snow version
  * 
*/ diff --git a/src/main/java/org/jcnc/snow/cli/doc/README.md b/src/main/java/org/jcnc/snow/cli/doc/README.md index b823c200..7244a38f 100644 --- a/src/main/java/org/jcnc/snow/cli/doc/README.md +++ b/src/main/java/org/jcnc/snow/cli/doc/README.md @@ -4,10 +4,13 @@ ## 项目简介 -**CLI(Command Line Interface)** 是 Snow 项目对外的统一入口,提供从初始化项目、解析依赖、编译、打包、运行到发布的一站式指令集。 -该模块以**薄封装/强委托**为设计目标:在 CLI 层完成参数解析、子命令分发与生命周期编排,将实际业务逻辑(编译/运行/打包/依赖解析等)委托给 `pkg` 层的任务与工具执行。 +**CLI(Command Line Interface)** 是 Snow +项目对外的统一入口,提供从初始化项目、解析依赖、编译、打包、运行到发布的一站式指令集。 +该模块以**薄封装/强委托**为设计目标:在 CLI 层完成参数解析、子命令分发与生命周期编排,将实际业务逻辑(编译/运行/打包/依赖解析等)委托给 +`pkg` 层的任务与工具执行。 -核心入口类 `SnowCLI` 通过注册一组 `CLICommand` 子命令(如 `build` / `compile` / `run` / `publish` 等),统一处理**全局帮助**、**版本信息**、**未知命令兜底**与**退出码约定**,并支持在将来通过 `ServiceLoader`/注册表扩展新的命令。 +核心入口类 `SnowCLI` 通过注册一组 `CLICommand` 子命令(如 `build` / `compile` / `run` / `publish` 等),统一处理**全局帮助 +**、**版本信息**、**未知命令兜底**与**退出码约定**,并支持在将来通过 `ServiceLoader`/注册表扩展新的命令。 ## 核心功能 @@ -34,7 +37,8 @@ * DSL 解析:`CloudDSLParser` 读取 `project.cloud` 为 `Project` 模型 * 依赖解析与缓存:`DependencyResolver`(默认缓存目录位于用户主目录 `~/.snow/cache`) - * 生命周期编排:`LifecycleManager` / `LifecyclePhase` 注册并顺序执行任务(如 `RESOLVE_DEPENDENCIES` / `COMPILE` / `PACKAGE` / `PUBLISH` / `CLEAN` / `INIT` 等) + * 生命周期编排:`LifecycleManager` / `LifecyclePhase` 注册并顺序执行任务(如 `RESOLVE_DEPENDENCIES` / `COMPILE` / + `PACKAGE` / `PUBLISH` / `CLEAN` / `INIT` 等) * 具体任务:`CompileTask`、`RunTask`、`PackageTask`、`GenerateTask`、`CleanTask`、`PublishTask`(CLI 仅做参数组装与委托) * **错误处理与退出码约定** diff --git a/src/main/java/org/jcnc/snow/compiler/backend/alloc/RegisterAllocator.java b/src/main/java/org/jcnc/snow/compiler/backend/alloc/RegisterAllocator.java index c7a1c112..6df97a89 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/alloc/RegisterAllocator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/alloc/RegisterAllocator.java @@ -15,7 +15,7 @@ import java.util.Map; * 各虚拟寄存器实际对应的物理寄存器或栈槽号。采用简单的线性扫描分配策略。 *

*

- * 分配过程如下: + * 分配过程如下: *

    *
  1. 优先为函数参数分配槽号,从 0 开始,按参数顺序递增。
  2. *
  3. 遍历函数体的每条指令,为尚未分配的目标寄存器及其操作数分配新的槽号。
  4. @@ -37,7 +37,7 @@ public final class RegisterAllocator { /** * 为指定 IR 函数分配所有虚拟寄存器的槽号。 *

    - * 分配顺序说明: + * 分配顺序说明: *

      *
    1. 首先为所有参数分配槽号。
    2. *
    3. 然后线性遍历函数体,为每个指令涉及的虚拟寄存器(目标或操作数)分配槽号, @@ -47,7 +47,7 @@ public final class RegisterAllocator { *

      * * @param fn 需要进行寄存器分配的 IR 函数对象 - * @return 一个不可变映射,记录所有虚拟寄存器到槽号的分配关系 + * @return 一个不可变映射,记录所有虚拟寄存器到槽号的分配关系 */ public Map allocate(IRFunction fn) { int next = 0; // 下一个可分配的槽编号 diff --git a/src/main/java/org/jcnc/snow/compiler/backend/builder/VMCodeGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/builder/VMCodeGenerator.java index e764e41e..030af050 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/builder/VMCodeGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/builder/VMCodeGenerator.java @@ -5,6 +5,7 @@ import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.core.IRFunction; import org.jcnc.snow.compiler.ir.core.IRInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; + import java.util.List; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/core/InstructionGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/core/InstructionGenerator.java index f7acfd15..ba7c9950 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/core/InstructionGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/core/InstructionGenerator.java @@ -25,10 +25,10 @@ public interface InstructionGenerator { /** * 将一条 IR 指令翻译为对应的 VM 指令序列。 * - * @param ins 当前待翻译的 IR 指令 - * @param out 虚拟机程序构建器,用于输出 VM 指令 - * @param slotMap 虚拟寄存器与实际槽号的映射关系 - * @param currentFn 当前函数名称(用于作用域或调试等) + * @param ins 当前待翻译的 IR 指令 + * @param out 虚拟机程序构建器,用于输出 VM 指令 + * @param slotMap 虚拟寄存器与实际槽号的映射关系 + * @param currentFn 当前函数名称(用于作用域或调试等) */ void generate(T ins, VMProgramBuilder out, Map slotMap, String currentFn); } diff --git a/src/main/java/org/jcnc/snow/compiler/backend/doc/README.md b/src/main/java/org/jcnc/snow/compiler/backend/doc/README.md index 743fbac9..826e745f 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/doc/README.md +++ b/src/main/java/org/jcnc/snow/compiler/backend/doc/README.md @@ -4,8 +4,10 @@ ## 项目简介 -**Backend(IR→VM)** 模块承接 IR 层产物,完成**寄存器分配**、**操作码映射与类型提升**、**指令选择与输出组装**,最终生成可在 Snow VM 上执行的指令流。 -模块采用“**指令生成器(InstructionGenerator)+ 注册表**”的可插拔架构:每种 IR 指令对应一个生成器;`VMCodeGenerator` 负责分发与调度;`VMProgramBuilder` 负责落盘(emit)、标签/调用回填(fixup)与函数边界管理。 +**Backend(IR→VM)** 模块承接 IR 层产物,完成**寄存器分配**、**操作码映射与类型提升**、**指令选择与输出组装**,最终生成可在 +Snow VM 上执行的指令流。 +模块采用“**指令生成器(InstructionGenerator)+ 注册表**”的可插拔架构:每种 IR 指令对应一个生成器;`VMCodeGenerator` 负责分发与调度; +`VMProgramBuilder` 负责落盘(emit)、标签/调用回填(fixup)与函数边界管理。 ## 核心功能 @@ -84,7 +86,8 @@ backend/ 1. **寄存器分配**:对每个 `IRFunction` 调用 `RegisterAllocator#allocate(fn)` → 产出 `slotMap`。 2. **创建输出器**:`VMProgramBuilder out = new VMProgramBuilder()`。 -3. **构建代码生成器**:`VMCodeGenerator gen = new VMCodeGenerator(slotMap, out, InstructionGeneratorProvider.defaultGenerators())`。 +3. **构建代码生成器**: + `VMCodeGenerator gen = new VMCodeGenerator(slotMap, out, InstructionGeneratorProvider.defaultGenerators())`。 4. **逐函数生成**:`gen.generate(fn)`(内部:遍历 IR 指令 → 分派到对应 `InstructionGenerator` → 结束处自动发出 `HALT/RET`)。 5. **收集结果**:`out.build()` / `out.getCode()` 取得最终 VM 指令序列(`String` 列表),可直接喂给 VM 或写出文本。 diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java index 02e4bd4d..f39c342a 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java @@ -1,9 +1,9 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper; -import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; +import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.backend.utils.TypePromoteUtils; import org.jcnc.snow.compiler.ir.instruction.IRCompareJumpInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; @@ -17,7 +17,7 @@ import java.util.Map; * 负责将 IR 中的 {@link IRCompareJumpInstruction}(条件比较并跳转指令) * 转换为目标虚拟机(VM)可执行的指令序列。 *

      - * + *

      * 主要功能 *

        *
      • 根据 IR 比较指令左右操作数的类型,自动进行类型提升与转换
      • @@ -52,17 +52,17 @@ public class CmpJumpGenerator implements InstructionGenerator slotMap, - String currentFn) { + public void generate(IRCompareJumpInstruction ins, + VMProgramBuilder out, + Map slotMap, + String currentFn) { // 1. 获取左右操作数的槽位与静态类型 - int leftSlot = slotMap.get(ins.left()); - int rightSlot = slotMap.get(ins.right()); - char lType = out.getSlotType(leftSlot); - char rType = out.getSlotType(rightSlot); - char tType = TypePromoteUtils.promote(lType, rType); // 公共类型提升 + int leftSlot = slotMap.get(ins.left()); + int rightSlot = slotMap.get(ins.right()); + char lType = out.getSlotType(leftSlot); + char rType = out.getSlotType(rightSlot); + char tType = TypePromoteUtils.promote(lType, rType); // 公共类型提升 // 2. 加载左右操作数并按需类型转换 // 左操作数 diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/InstructionGeneratorProvider.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/InstructionGeneratorProvider.java index 2b2517da..ef6996cf 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/InstructionGeneratorProvider.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/InstructionGeneratorProvider.java @@ -13,10 +13,9 @@ import java.util.List; */ public final class InstructionGeneratorProvider { - /** 工具类禁止实例化。 */ - private InstructionGeneratorProvider() { /* no-instance */ } - - /** 缺省指令生成器列表(不可修改,顺序即执行顺序)。 */ + /** + * 缺省指令生成器列表(不可修改,顺序即执行顺序)。 + */ private static final List> DEFAULT = List.of( new LoadConstGenerator(), // 常量加载 @@ -29,6 +28,11 @@ public final class InstructionGeneratorProvider { new CmpJumpGenerator() // 条件跳转 ); + /** + * 工具类禁止实例化。 + */ + private InstructionGeneratorProvider() { /* no-instance */ } + /** * 返回生产环境使用的缺省指令生成器列表。 * 该列表为不可变集合,如尝试修改将抛出 diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java index c8426b32..ef07d6b8 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/JumpGenerator.java @@ -1,8 +1,8 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.instruction.IRJumpInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java index a3de5739..8cee1d71 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/UnaryOpGenerator.java @@ -1,9 +1,9 @@ package org.jcnc.snow.compiler.backend.generator; -import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper; -import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder; import org.jcnc.snow.compiler.backend.core.InstructionGenerator; +import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper; +import org.jcnc.snow.compiler.backend.utils.OpHelper; import org.jcnc.snow.compiler.ir.instruction.UnaryOperationInstruction; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; @@ -43,10 +43,10 @@ public class UnaryOpGenerator implements InstructionGenerator - * 类型优先级从高到低依次为: + * 类型优先级从高到低依次为: * D(double): 6 * F(float) : 5 * L(long) : 4 @@ -19,7 +19,7 @@ public class TypePromoteUtils { /** * 返回数值类型的宽度优先级,数值越大类型越宽。 - * 类型及优先级映射如下: + * 类型及优先级映射如下: * D(double): 6 * F(float) : 5 * L(long) : 4 @@ -70,7 +70,7 @@ public class TypePromoteUtils { * 如果源类型和目标类型相同,则返回 null,表示无需转换。 *

        * 支持的类型标记字符包括: B(byte)、S(short)、I(int)、L(long)、F(float)、D(double)。 - * 所有可能的类型转换均已覆盖,如下所示: + * 所有可能的类型转换均已覆盖,如下所示: * B → S/I/L/F/D * S → B/I/L/F/D * I → B/S/L/F/D diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java index 08169f07..4df33b4d 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java @@ -23,26 +23,125 @@ import java.util.Map; */ public final class IRBuilderScope { - /** 变量名到虚拟寄存器的映射表(本地变量) */ + /** + * 结构体字段布局表:结构体名 → (字段名 → 槽位下标) + */ + private static final Map> STRUCT_LAYOUTS = new HashMap<>(); + /** + * 结构体继承关系表:子类名 → 父类名 + */ + private static final Map STRUCT_PARENTS = new HashMap<>(); + /** + * 变量名到虚拟寄存器的映射表(本地变量) + */ private final Map vars = new HashMap<>(); - /** 变量名到类型字符串的映射表 */ + /** + * 变量名到类型字符串的映射表 + */ private final Map varTypes = new HashMap<>(); - /** 变量名到编译期常量值的映射表(本作用域) */ + /** + * 变量名到编译期常量值的映射表(本作用域) + */ private final Map varConstValues = new HashMap<>(); - - /** 存放跨模块导入的全局常量(如 ModuleA.a) */ + /** + * 存放跨模块导入的全局常量(如 ModuleA.a) + */ private final Map externalConsts = new HashMap<>(); + /** + * 当前作用域所绑定的 IRFunction 实例,用于变量分配新寄存器等。 + */ + private IRFunction fn; - /** 结构体字段布局表:结构体名 → (字段名 → 槽位下标) */ - private static final Map> STRUCT_LAYOUTS = new HashMap<>(); + // ---------------- 作用域与变量 ---------------- - /** 结构体继承关系表:子类名 → 父类名 */ - private static final Map STRUCT_PARENTS = new HashMap<>(); + /** + * 全局注册结构体的字段布局映射(字段名 -> 槽位下标)。 + * 一般在语义分析/IR 前期由类型系统收集后调用。 + * + * @param structName 结构体名(建议为简单名,如 "Animal";如有模块前缀也可) + * @param fieldToIndex 字段名到下标的映射(下标从 0 递增) + */ + static void registerStructLayout(String structName, Map fieldToIndex) { + if (structName == null || fieldToIndex == null) return; + // 覆盖式注册:方便增量/重复编译时刷新 + STRUCT_LAYOUTS.put(structName, new HashMap<>(fieldToIndex)); + } - /** 当前作用域所绑定的 IRFunction 实例,用于变量分配新寄存器等。 */ - private IRFunction fn; + /** + * 读取某结构体的完整字段布局(返回只读 Map)。 + * 支持“模块.结构体”及简单名两种写法。 + * + * @param structName 结构体名 + * @return 字段名到下标映射的只读视图,或 null + */ + public static Map getStructLayout(String structName) { + Map layout = STRUCT_LAYOUTS.get(structName); + if (layout == null && structName != null) { + int dot = structName.lastIndexOf('.'); + if (dot >= 0 && dot + 1 < structName.length()) { + layout = STRUCT_LAYOUTS.get(structName.substring(dot + 1)); + } + } + return layout == null ? null : Collections.unmodifiableMap(layout); + } - // ---------------- 作用域与变量 ---------------- + /** + * 注册结构体的父类信息。 + *

        + * 该方法用于维护结构体与其父类之间的映射关系。通过调用此方法, + * 可以为某个结构体名称指定其父结构体名称,并保存到全局的 + * {@code STRUCT_PARENTS} 映射中。 + *

        + * + * @param structName 子结构体的名称,不能为空或 {@code null} + * @param parentName 父结构体的名称,不能为空、不能为 {@code null} 或空白 + */ + static void registerStructParent(String structName, String parentName) { + if (structName == null || parentName == null || parentName.isBlank()) return; + STRUCT_PARENTS.put(structName, parentName); + } + + /** + * 获取某个结构体的父结构体名称。 + *

        + * 查询逻辑如下: + *

          + *
        1. 首先直接从 {@code STRUCT_PARENTS} 中查找对应的父结构体。
        2. + *
        3. 如果未找到,且 {@code structName} 含有点号(.),则提取点号后的简单类名进行查找。
        4. + *
        5. 如果仍未找到,则遍历 {@code STRUCT_PARENTS} 的所有条目: + *
            + *
          • 检查键(key)是否包含点号,若存在,则取其最后一个点号后的子串作为简单类名。
          • + *
          • 如果该简单类名与传入的 {@code structName} 相等,则返回对应的父类名称。
          • + *
          + *
        6. + *
        7. 如果所有方式都未找到,则返回 {@code null}。
        8. + *
        + *

        + * + * @param structName 需要查找父类的结构体名称,可以是完整类名或简单类名 + * @return 父结构体名称;如果未找到,返回 {@code null} + */ + public static String getStructParent(String structName) { + if (structName == null || structName.isBlank()) return null; + String p = STRUCT_PARENTS.get(structName); + if (p != null) return p; + + int dot = structName.lastIndexOf('.'); + if (dot >= 0 && dot + 1 < structName.length()) { + String simple = structName.substring(dot + 1); + p = STRUCT_PARENTS.get(simple); + if (p != null) return p; + } + + for (Map.Entry e : STRUCT_PARENTS.entrySet()) { + String k = e.getKey(); + int d = k.lastIndexOf('.'); + if (d >= 0 && d + 1 < k.length() && k.substring(d + 1).equals(structName)) { + return e.getValue(); + } + } + return null; + } /** * 绑定当前作用域到指定 IRFunction。 @@ -79,6 +178,8 @@ public final class IRBuilderScope { varConstValues.remove(name); // 重复声明也会清除常量绑定 } + // ---------------- 编译期常量 ---------------- + /** * 更新变量的虚拟寄存器绑定(如变量已存在则覆盖,否则等同于新声明)。 * @@ -109,6 +210,8 @@ public final class IRBuilderScope { return varTypes.get(name); } + // ---------------- 跨模块常量导入支持 ---------------- + /** * 获取变量名到类型名映射的不可变副本。 * @@ -118,7 +221,7 @@ public final class IRBuilderScope { return Collections.unmodifiableMap(varTypes); } - // ---------------- 编译期常量 ---------------- + // ---------------- 结构体字段布局(全局静态) ---------------- /** * 设置变量的编译期常量值(本地变量)。 @@ -157,7 +260,7 @@ public final class IRBuilderScope { varConstValues.remove(name); } - // ---------------- 跨模块常量导入支持 ---------------- + // ---------------- 结构体继承关系 ---------------- /** * 导入外部(其他模块)的全局常量/变量。 @@ -169,21 +272,6 @@ public final class IRBuilderScope { externalConsts.put(qualifiedName, value); } - // ---------------- 结构体字段布局(全局静态) ---------------- - - /** - * 全局注册结构体的字段布局映射(字段名 -> 槽位下标)。 - * 一般在语义分析/IR 前期由类型系统收集后调用。 - * - * @param structName 结构体名(建议为简单名,如 "Animal";如有模块前缀也可) - * @param fieldToIndex 字段名到下标的映射(下标从 0 递增) - */ - static void registerStructLayout(String structName, Map fieldToIndex) { - if (structName == null || fieldToIndex == null) return; - // 覆盖式注册:方便增量/重复编译时刷新 - STRUCT_LAYOUTS.put(structName, new HashMap<>(fieldToIndex)); - } - /** * 查询字段槽位下标。 * 支持“模块.结构体”及简单名两种写法自动兼容。 @@ -206,81 +294,4 @@ public final class IRBuilderScope { return layout.get(fieldName); } - /** - * 读取某结构体的完整字段布局(返回只读 Map)。 - * 支持“模块.结构体”及简单名两种写法。 - * - * @param structName 结构体名 - * @return 字段名到下标映射的只读视图,或 null - */ - public static Map getStructLayout(String structName) { - Map layout = STRUCT_LAYOUTS.get(structName); - if (layout == null && structName != null) { - int dot = structName.lastIndexOf('.'); - if (dot >= 0 && dot + 1 < structName.length()) { - layout = STRUCT_LAYOUTS.get(structName.substring(dot + 1)); - } - } - return layout == null ? null : Collections.unmodifiableMap(layout); - } - - // ---------------- 结构体继承关系 ---------------- - /** - * 注册结构体的父类信息。 - *

        - * 该方法用于维护结构体与其父类之间的映射关系。通过调用此方法, - * 可以为某个结构体名称指定其父结构体名称,并保存到全局的 - * {@code STRUCT_PARENTS} 映射中。 - *

        - * - * @param structName 子结构体的名称,不能为空或 {@code null} - * @param parentName 父结构体的名称,不能为空、不能为 {@code null} 或空白 - */ - static void registerStructParent(String structName, String parentName) { - if (structName == null || parentName == null || parentName.isBlank()) return; - STRUCT_PARENTS.put(structName, parentName); - } - - /** - * 获取某个结构体的父结构体名称。 - *

        - * 查询逻辑如下: - *

          - *
        1. 首先直接从 {@code STRUCT_PARENTS} 中查找对应的父结构体。
        2. - *
        3. 如果未找到,且 {@code structName} 含有点号(.),则提取点号后的简单类名进行查找。
        4. - *
        5. 如果仍未找到,则遍历 {@code STRUCT_PARENTS} 的所有条目: - *
            - *
          • 检查键(key)是否包含点号,若存在,则取其最后一个点号后的子串作为简单类名。
          • - *
          • 如果该简单类名与传入的 {@code structName} 相等,则返回对应的父类名称。
          • - *
          - *
        6. - *
        7. 如果所有方式都未找到,则返回 {@code null}。
        8. - *
        - *

        - * - * @param structName 需要查找父类的结构体名称,可以是完整类名或简单类名 - * @return 父结构体名称;如果未找到,返回 {@code null} - */ - public static String getStructParent(String structName) { - if (structName == null || structName.isBlank()) return null; - String p = STRUCT_PARENTS.get(structName); - if (p != null) return p; - - int dot = structName.lastIndexOf('.'); - if (dot >= 0 && dot + 1 < structName.length()) { - String simple = structName.substring(dot + 1); - p = STRUCT_PARENTS.get(simple); - if (p != null) return p; - } - - for (Map.Entry e : STRUCT_PARENTS.entrySet()) { - String k = e.getKey(); - int d = k.lastIndexOf('.'); - if (d >= 0 && d + 1 < k.length() && k.substring(d + 1).equals(structName)) { - return e.getValue(); - } - } - return null; - } - } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRContext.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRContext.java index f1074347..9c125668 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRContext.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRContext.java @@ -22,16 +22,21 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; */ public class IRContext { - /** label 自动生成计数器,用于保证唯一性 */ - private int labelCounter = 0; - - /** 当前正在构建的 IRFunction 对象,所有 IR 指令均将添加至此 */ + /** + * 当前正在构建的 IRFunction 对象,所有 IR 指令均将添加至此 + */ private final IRFunction function; - - /** 用于管理当前函数作用域内变量与虚拟寄存器、类型等的映射关系 */ + /** + * 用于管理当前函数作用域内变量与虚拟寄存器、类型等的映射关系 + */ private final IRBuilderScope scope; - - /** 当前 declare 编译阶段变量类型,不在变量声明流程时为 null */ + /** + * label 自动生成计数器,用于保证唯一性 + */ + private int labelCounter = 0; + /** + * 当前 declare 编译阶段变量类型,不在变量声明流程时为 null + */ private String varType; /** @@ -47,7 +52,9 @@ public class IRContext { this.varType = null; } - /** 获取当前正在构建的 IRFunction 对象。 */ + /** + * 获取当前正在构建的 IRFunction 对象。 + */ public IRFunction getFunction() { return function; } @@ -60,7 +67,9 @@ public class IRContext { return scope; } - /** 为当前函数分配一个新的虚拟寄存器。 */ + /** + * 为当前函数分配一个新的虚拟寄存器。 + */ public IRVirtualRegister newRegister() { return function.newRegister(); } @@ -76,7 +85,9 @@ public class IRContext { return newRegister(); } - /** 将指定的 IRInstruction 添加到当前 IRFunction 的指令列表中。 */ + /** + * 将指定的 IRInstruction 添加到当前 IRFunction 的指令列表中。 + */ public void addInstruction(IRInstruction instr) { function.add(instr); } @@ -91,17 +102,23 @@ public class IRContext { return "L" + (labelCounter++); } - /** 获取当前 declare 编译阶段变量类型(声明流程中临时记录) */ + /** + * 获取当前 declare 编译阶段变量类型(声明流程中临时记录) + */ public String getVarType() { return varType; } - /** 设置当前 declare 编译阶段变量类型(一般在变量声明时赋值) */ + /** + * 设置当前 declare 编译阶段变量类型(一般在变量声明时赋值) + */ public void setVarType(String type) { this.varType = type; } - /** 清除当前 declare 编译阶段变量类型(声明流程结束时调用) */ + /** + * 清除当前 declare 编译阶段变量类型(声明流程结束时调用) + */ public void clearVarType() { this.varType = null; } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRProgramBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRProgramBuilder.java index 0260c07b..b0f42ffe 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRProgramBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRProgramBuilder.java @@ -97,6 +97,7 @@ public final class IRProgramBuilder { *
      • 最后将布局以 StructName 为键注册到 {@link IRBuilderScope} 的全局布局表。
      • *
      • 同时调用 {@link IRBuilderScope#registerStructParent} 登记继承关系(子类 → 父类)。
      • *
    + * * @param roots AST 顶层节点列表,包含模块/结构体信息 */ private void preloadStructLayouts(List roots) { diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/UnaryHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/UnaryHandler.java index d562cde9..67afc7cf 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/UnaryHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/UnaryHandler.java @@ -22,7 +22,7 @@ public class UnaryHandler implements ExpressionHandler { * * @param b 表达式构建器 * @param un 一元表达式 AST 节点 - * @return 存放一元表达式结果的虚拟寄存器 + * @return 存放一元表达式结果的虚拟寄存器 */ @Override public IRVirtualRegister handle(ExpressionBuilder b, UnaryExpressionNode un) { diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/FunctionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/FunctionBuilder.java index 0092d228..0d2f595c 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/FunctionBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/FunctionBuilder.java @@ -51,7 +51,7 @@ public class FunctionBuilder { // 2) 初始化 IR 容器与上下文 IRFunction irFunction = new IRFunction(functionNode.name()); - IRContext irContext = new IRContext(irFunction); + IRContext irContext = new IRContext(irFunction); // 3) 导入所有全局/跨模块常量到当前作用域(便于常量折叠和跨模块引用) GlobalConstTable.all().forEach((k, v) -> @@ -66,11 +66,11 @@ public class FunctionBuilder { // 仅在浮点/整型长短类型上设置;其它/void 情况不设置(使用 '\0' 表示不设置) char defaultSuffix = switch (rtLower) { case "double" -> 'd'; - case "float" -> 'f'; - case "long" -> 'l'; - case "short" -> 's'; - case "byte" -> 'b'; - default -> '\0'; + case "float" -> 'f'; + case "long" -> 'l'; + case "short" -> 's'; + case "byte" -> 'b'; + default -> '\0'; }; ExpressionUtils.setDefaultSuffix(defaultSuffix); diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/IfHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/IfHandler.java index 08f1b080..41095ae5 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/IfHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/IfHandler.java @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.ir.builder.statement.handlers; import org.jcnc.snow.compiler.ir.builder.core.InstructionFactory; import org.jcnc.snow.compiler.ir.builder.statement.IStatementHandler; -import org.jcnc.snow.compiler.ir.builder.statement.utils.ConditionalJump; import org.jcnc.snow.compiler.ir.builder.statement.StatementBuilderContext; +import org.jcnc.snow.compiler.ir.builder.statement.utils.ConditionalJump; import org.jcnc.snow.compiler.parser.ast.IfNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/LoopHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/LoopHandler.java index 4542dc55..50747288 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/LoopHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/LoopHandler.java @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.ir.builder.statement.handlers; import org.jcnc.snow.compiler.ir.builder.core.InstructionFactory; import org.jcnc.snow.compiler.ir.builder.statement.IStatementHandler; -import org.jcnc.snow.compiler.ir.builder.statement.utils.ConditionalJump; import org.jcnc.snow.compiler.ir.builder.statement.StatementBuilderContext; +import org.jcnc.snow.compiler.ir.builder.statement.utils.ConditionalJump; import org.jcnc.snow.compiler.parser.ast.LoopNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConditionalJump.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConditionalJump.java index 0f27e0d0..1ddd06ac 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConditionalJump.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConditionalJump.java @@ -6,9 +6,9 @@ import org.jcnc.snow.compiler.ir.core.IROpCode; import org.jcnc.snow.compiler.ir.utils.ComparisonUtils; import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; +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.ast.BinaryExpressionNode; /** * 条件跳转指令工具类。 diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConstFolder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConstFolder.java index 7fcc8522..0915ddd2 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConstFolder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/utils/ConstFolder.java @@ -2,7 +2,6 @@ package org.jcnc.snow.compiler.ir.builder.statement.utils; import org.jcnc.snow.compiler.ir.builder.statement.StatementBuilderContext; import org.jcnc.snow.compiler.parser.ast.*; - import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import java.util.ArrayList; diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/utils/IndexRefHelper.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/utils/IndexRefHelper.java index 13161eb3..e5c2e0c6 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/utils/IndexRefHelper.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/utils/IndexRefHelper.java @@ -25,7 +25,7 @@ public record IndexRefHelper(ExpressionBuilder builder) { * 若可做常量折叠,直接返回常量寄存器;否则递归处理每层,最终生成 __index_r 指令,返回中间层的引用。 * * @param node 多维下标 AST 节点 - * @return 存放下标引用的虚拟寄存器 + * @return 存放下标引用的虚拟寄存器 */ public IRVirtualRegister build(IndexExpressionNode node) { // 1. 常量折叠:编译期求值优化 diff --git a/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalConstTable.java b/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalConstTable.java index ad9795be..8003b9a8 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalConstTable.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalConstTable.java @@ -26,7 +26,9 @@ import java.util.concurrent.ConcurrentHashMap; */ public final class GlobalConstTable { - /** 存储全局常量: “ModuleName.constName” → 常量值。线程安全。 */ + /** + * 存储全局常量: “ModuleName.constName” → 常量值。线程安全。 + */ private static final Map CONSTS = new ConcurrentHashMap<>(); /** diff --git a/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalFunctionTable.java b/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalFunctionTable.java index 71057049..c80abde8 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalFunctionTable.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/common/GlobalFunctionTable.java @@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentHashMap; * 此工具类用于在编译前端构建每个函数 IR(中间表示)时登记函数的返回类型, * 以便后端在生成 {@code CALL} 指令时判断是否需要保存返回值。 *

    - * + *

    * 使用说明 *

      *
    • 在函数 IR 构建阶段,调用 {@link #register(String, String)} 方法登记函数名与返回类型。
    • diff --git a/src/main/java/org/jcnc/snow/compiler/ir/core/IRFunction.java b/src/main/java/org/jcnc/snow/compiler/ir/core/IRFunction.java index 2179e5a0..457d7e08 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/core/IRFunction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/core/IRFunction.java @@ -24,16 +24,14 @@ public class IRFunction { * IR 指令列表,组成函数体。 */ private final List body = new ArrayList<>(); - - /** - * 用于生成新的虚拟寄存器编号的计数器。 - */ - private int regCounter = 0; - /** * 正式参数所对应的虚拟寄存器列表,按声明顺序排列。 */ private final List parameters = new ArrayList<>(); + /** + * 用于生成新的虚拟寄存器编号的计数器。 + */ + private int regCounter = 0; /** * 构造一个具有指定名称的 IRFunction 实例。 @@ -112,7 +110,7 @@ public class IRFunction { } /** - * 以IR代码表示,示例: + * 以IR代码表示,示例: *
            * func 名称(%0, %1, ...) {
            *   指令0
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/core/IRInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/core/IRInstruction.java
      index 2821d586..4977526b 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/core/IRInstruction.java
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/core/IRInstruction.java
      @@ -1,6 +1,7 @@
       package org.jcnc.snow.compiler.ir.core;
       
       import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
      +
       import java.util.List;
       
       /**
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/doc/README.md b/src/main/java/org/jcnc/snow/compiler/ir/doc/README.md
      index ce3e936f..edc47082 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/doc/README.md
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/doc/README.md
      @@ -7,7 +7,9 @@
       **IR(Intermediate Representation)** 是 Snow 编译器项目的核心模块,承担中间表示的构建、组织与管理任务。
       它用于在前端语法分析与后端目标代码生成之间,提供结构清晰、便于优化和转换的抽象表示形式。
       
      -本 IR 模块采用**类 SSA(Static Single Assignment)** 的思路:以**虚拟寄存器**为中心组织数据流,配合**统一的操作码集(`IROpCode`)**、**访问者模式(`IRVisitor`)**与**构建器体系**,形成可扩展、可调试、且便于后续优化与代码生成的 IR 层。
      +本 IR 模块采用**类 SSA(Static Single Assignment)** 的思路:以**虚拟寄存器**为中心组织数据流,配合*
      +*统一的操作码集(`IROpCode`)**、**访问者模式(`IRVisitor`)**与**构建器体系**,形成可扩展、可调试、且便于后续优化与代码生成的
      +IR 层。
       
       ## 核心功能
       
      @@ -36,7 +38,8 @@
       * **操作码与类型提升**
       
           * `IROpCode` 定义全量操作码(整数/浮点不同位宽的算术、比较、转换,`LOAD/STORE/CONST`,`JUMP/LABEL/CALL/RET` 等)
      -    * `IROpCodeMappings`/`ExpressionUtils`/`ComparisonUtils` 负责从 AST 运算符与操作数类型推导到具体 IR 操作码,并进行必要的类型提升与比较归类
      +    * `IROpCodeMappings`/`ExpressionUtils`/`ComparisonUtils` 负责从 AST 运算符与操作数类型推导到具体 IR
      +      操作码,并进行必要的类型提升与比较归类
       * **IR 打印与调试支持**
       
           * `IRPrinter`:基于访问者输出 IR(便于调试/测试)
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/BinaryOperationInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/BinaryOperationInstruction.java
      index cd83ddec..11da45ad 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/BinaryOperationInstruction.java
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/BinaryOperationInstruction.java
      @@ -17,16 +17,24 @@ import java.util.List;
        */
       public final class BinaryOperationInstruction extends IRInstruction {
       
      -    /** 指令操作符,如 ADD_I32、SUB_I32 等,取自 IROpCode 枚举 */
      +    /**
      +     * 指令操作符,如 ADD_I32、SUB_I32 等,取自 IROpCode 枚举
      +     */
           private final IROpCode op;
       
      -    /** 运算结果将写入的目标虚拟寄存器 */
      +    /**
      +     * 运算结果将写入的目标虚拟寄存器
      +     */
           private final IRVirtualRegister dest;
       
      -    /** 运算的左操作数 */
      +    /**
      +     * 运算的左操作数
      +     */
           private final IRValue lhs;
       
      -    /** 运算的右操作数 */
      +    /**
      +     * 运算的右操作数
      +     */
           private final IRValue rhs;
       
           /**
      @@ -38,10 +46,10 @@ public final class BinaryOperationInstruction extends IRInstruction {
            * @param rhs  右操作数
            */
           public BinaryOperationInstruction(IROpCode op, IRVirtualRegister dest, IRValue lhs, IRValue rhs) {
      -        this.op   = op;
      +        this.op = op;
               this.dest = dest;
      -        this.lhs  = lhs;
      -        this.rhs  = rhs;
      +        this.lhs = lhs;
      +        this.rhs = rhs;
           }
       
           /**
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java
      index dd963d97..b81856b4 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/CallInstruction.java
      @@ -19,11 +19,17 @@ import java.util.List;
        * 并且不会参与寄存器分配。
        */
       public class CallInstruction extends IRInstruction {
      -    /** 调用结果目标寄存器;void 返回时可为 null */
      +    /**
      +     * 调用结果目标寄存器;void 返回时可为 null
      +     */
           private final IRVirtualRegister dest;
      -    /** 被调用的函数名(含模块限定) */
      +    /**
      +     * 被调用的函数名(含模块限定)
      +     */
           private final String functionName;
      -    /** 实参列表 */
      +    /**
      +     * 实参列表
      +     */
           private final List arguments;
       
           public CallInstruction(IRVirtualRegister dest,
      @@ -40,13 +46,17 @@ public class CallInstruction extends IRInstruction {
               return IROpCode.CALL;
           }
       
      -    /** 仅在函数有返回值时才暴露目标寄存器 */
      +    /**
      +     * 仅在函数有返回值时才暴露目标寄存器
      +     */
           @Override
           public IRVirtualRegister dest() {
               return isVoidReturn() ? null : dest;
           }
       
      -    /** 操作数列表: void 调用不包含 dest */
      +    /**
      +     * 操作数列表: void 调用不包含 dest
      +     */
           @Override
           public List operands() {
               List ops = new ArrayList<>();
      @@ -71,7 +81,10 @@ public class CallInstruction extends IRInstruction {
           }
       
           // === 帮助方法 ===
      -    /** 判断被调函数是否返回 void */
      +
      +    /**
      +     * 判断被调函数是否返回 void
      +     */
           private boolean isVoidReturn() {
               return "void".equals(GlobalFunctionTable.getReturnType(functionName));
           }
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRAddInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRAddInstruction.java
      index 4df8d8dc..b5a61897 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRAddInstruction.java
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRAddInstruction.java
      @@ -17,13 +17,19 @@ import java.util.List;
        */
       public class IRAddInstruction extends IRInstruction {
       
      -    /** 运算结果存放的目标虚拟寄存器 */
      +    /**
      +     * 运算结果存放的目标虚拟寄存器
      +     */
           private final IRVirtualRegister dest;
       
      -    /** 左操作数 */
      +    /**
      +     * 左操作数
      +     */
           private final IRValue lhs;
       
      -    /** 右操作数 */
      +    /**
      +     * 右操作数
      +     */
           private final IRValue rhs;
       
           /**
      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRCompareJumpInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRCompareJumpInstruction.java
      index 74d472db..6c9c8cf8 100644
      --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRCompareJumpInstruction.java
      +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRCompareJumpInstruction.java
      @@ -6,8 +6,8 @@ import org.jcnc.snow.compiler.ir.core.IRVisitor;
       import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
       
       /**
      - * “比较 + 条件跳转” 复合指令: 
      - *   if ( left  right ) jump targetLabel;
      + * “比较 + 条件跳转” 复合指令:
      + * if ( left  right ) jump targetLabel;
        * 

      * 其中 cmpOp 只能是 IROpCode.CMP_* 六种比较操作码。 */ @@ -22,7 +22,7 @@ public final class IRCompareJumpInstruction extends IRInstruction { IRVirtualRegister right, String targetLabel) { this.cmpOp = cmpOp; - this.left = left; + this.left = left; this.right = right; this.targetLabel = targetLabel; } @@ -32,16 +32,26 @@ public final class IRCompareJumpInstruction extends IRInstruction { return cmpOp; } - public IRVirtualRegister left() { return left; } - public IRVirtualRegister right() { return right; } - public String label() { return targetLabel; } + public IRVirtualRegister left() { + return left; + } + + public IRVirtualRegister right() { + return right; + } + + public String label() { + return targetLabel; + } @Override public String toString() { return cmpOp + " " + left + ", " + right + " -> " + targetLabel; } - /** 暂无访问者实现,留空 */ + /** + * 暂无访问者实现,留空 + */ @Override public void accept(IRVisitor visitor) { /* no-op */ } } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRJumpInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRJumpInstruction.java index 96b83ce5..3112b9ec 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRJumpInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRJumpInstruction.java @@ -12,7 +12,9 @@ import org.jcnc.snow.compiler.ir.core.IRVisitor; */ public class IRJumpInstruction extends IRInstruction { - /** 跳转目标的标签名 */ + /** + * 跳转目标的标签名 + */ private final String label; /** diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRLabelInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRLabelInstruction.java index 8198b44d..e73262a3 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRLabelInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRLabelInstruction.java @@ -31,7 +31,9 @@ public final class IRLabelInstruction extends IRInstruction { return name + ":"; } - /** 目前尚未对 Label 做访问者处理,空实现即可 */ + /** + * 目前尚未对 Label 做访问者处理,空实现即可 + */ @Override public void accept(IRVisitor visitor) { /* no-op */ diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRReturnInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRReturnInstruction.java index 0aa50715..3bdce77b 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRReturnInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/IRReturnInstruction.java @@ -16,7 +16,9 @@ import java.util.List; */ public class IRReturnInstruction extends IRInstruction { - /** 要返回的值,可以是常量、虚拟寄存器等 */ + /** + * 要返回的值,可以是常量、虚拟寄存器等 + */ private final IRValue returnValue; /** diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/LoadConstInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/LoadConstInstruction.java index 3ef925a7..c5409e80 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/LoadConstInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/LoadConstInstruction.java @@ -17,10 +17,14 @@ import java.util.List; */ public final class LoadConstInstruction extends IRInstruction { - /** 要加载的常量值,类型为 IRConstant */ + /** + * 要加载的常量值,类型为 IRConstant + */ private final IRConstant k; - /** 存放常量结果的目标虚拟寄存器 */ + /** + * 存放常量结果的目标虚拟寄存器 + */ private final IRVirtualRegister dest; /** diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/ReturnInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/ReturnInstruction.java index f689e995..351369e5 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/ReturnInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/ReturnInstruction.java @@ -11,7 +11,7 @@ import java.util.List; /** * ReturnInstruction —— 表示函数返回指令,格式: RET 或 RET *

      - * 此类用于描述函数执行完毕后的返回操作。支持两种返回形式: + * 此类用于描述函数执行完毕后的返回操作。支持两种返回形式: * - 无返回值(void): 生成无参的 RET 指令 * - 有返回值: 将指定虚拟寄存器中的值返回给调用者 *

      diff --git a/src/main/java/org/jcnc/snow/compiler/ir/instruction/UnaryOperationInstruction.java b/src/main/java/org/jcnc/snow/compiler/ir/instruction/UnaryOperationInstruction.java index 0e02b764..06628f87 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/instruction/UnaryOperationInstruction.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/instruction/UnaryOperationInstruction.java @@ -14,7 +14,7 @@ import java.util.List; * 用于对单个操作数 val 执行指定的一元运算 OP(例如取负 NEG), * 并将结果写入目标虚拟寄存器 dest。 *

      - * 支持的操作由 {@link IROpCode} 定义,目前常见的一元操作包括: + * 支持的操作由 {@link IROpCode} 定义,目前常见的一元操作包括: *

        *
      • NEG_I32 —— 整数取负: dest = -val
      • *
      • (可扩展)逻辑非、按位非等
      • @@ -22,13 +22,19 @@ import java.util.List; */ public final class UnaryOperationInstruction extends IRInstruction { - /** 一元运算操作符(如 NEG_I32) */ + /** + * 一元运算操作符(如 NEG_I32) + */ private final IROpCode op; - /** 运算结果写入的目标虚拟寄存器 */ + /** + * 运算结果写入的目标虚拟寄存器 + */ private final IRVirtualRegister dest; - /** 被操作的值(唯一操作数) */ + /** + * 被操作的值(唯一操作数) + */ private final IRValue val; /** 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 75f388d6..c6c824e3 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 @@ -15,8 +15,8 @@ import java.util.Map; * 该类主要用于根据左右操作数的静态类型,自动选择正确的 IR 层比较操作码。 * 支持自动类型提升,保证 int、long、float、double 等类型的比较均能得到正确的 IR 指令。 *

        - * - * 类型判定支持: + *

        + * 类型判定支持: *

          *
        • 字面量后缀: 支持 B/S/I/L/F/D(大小写均可)
        • *
        • 浮点数支持: 如无后缀但有小数点,视为 double
        • @@ -24,7 +24,8 @@ import java.util.Map; *
        */ public final class ComparisonUtils { - private ComparisonUtils() {} + private ComparisonUtils() { + } /** * 判断给定字符串是否为受支持的比较运算符(==, !=, <, >, <=, >=)。 @@ -39,14 +40,14 @@ public final class ComparisonUtils { } /** - * 返回类型宽度优先级(越大代表类型越宽)。类型对应的优先级: - * - D (double): 6 - * - F (float): 5 - * - L (long): 4 - * - I (int): 3 - * - S (short): 2 - * - B (byte): 1 - * - 未知类型: 0 + * 返回类型宽度优先级(越大代表类型越宽)。类型对应的优先级: + * - D (double): 6 + * - F (float): 5 + * - L (long): 4 + * - I (int): 3 + * - S (short): 2 + * - B (byte): 1 + * - 未知类型: 0 * * @param p 类型标记字符 * @return 类型优先级数值 @@ -129,12 +130,18 @@ public final class ComparisonUtils { final String type = variables.get(name); if (type != null) { switch (type) { - case "byte": return 'B'; - case "short": return 'S'; - case "int": return 'I'; - case "long": return 'L'; - case "float": return 'F'; - case "double": return 'D'; + case "byte": + return 'B'; + case "short": + return 'S'; + case "int": + return 'I'; + case "long": + return 'L'; + case "float": + return 'F'; + case "double": + return 'D'; } } } 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 43aa9767..8cebf624 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 @@ -15,34 +15,39 @@ import java.util.Map; * 表达式分析与操作符选择工具类。 *

        * 主要功能: - * - 解析字面量常量,自动推断类型 - * - 自动匹配并选择适合的算术/比较操作码 - * - 表达式类型的合并与类型提升 - * - 支持线程隔离的函数级默认类型后缀 + * - 解析字面量常量,自动推断类型 + * - 自动匹配并选择适合的算术/比较操作码 + * - 表达式类型的合并与类型提升 + * - 支持线程隔离的函数级默认类型后缀 */ public final class ExpressionUtils { - private ExpressionUtils() {} - - // ───────────── 线程级默认类型后缀 ───────────── - /** * 当前线程的默认类型后缀(如当前函数返回类型等),用于类型推断兜底。 */ private static final ThreadLocal DEFAULT_SUFFIX = ThreadLocal.withInitial(() -> '\0'); + // ───────────── 线程级默认类型后缀 ───────────── + + private ExpressionUtils() { + } + /** * 设置当前线程的默认类型后缀。 * * @param suffix 类型后缀字符(b/s/i/l/f/d),'\0'表示无 */ - public static void setDefaultSuffix(char suffix) { DEFAULT_SUFFIX.set(suffix); } + public static void setDefaultSuffix(char suffix) { + DEFAULT_SUFFIX.set(suffix); + } /** * 清除当前线程的默认类型后缀,重置为无。 */ - public static void clearDefaultSuffix() { DEFAULT_SUFFIX.set('\0'); } + public static void clearDefaultSuffix() { + DEFAULT_SUFFIX.set('\0'); + } // ───────────── 字面量常量解析 ───────────── @@ -73,19 +78,19 @@ public final class ExpressionUtils { : Character.toLowerCase(value.charAt(value.length() - 1)); String digits = switch (suffix) { - case 'b','s','l','f','d' -> value.substring(0, value.length() - 1); + case 'b', 's', 'l', 'f', 'd' -> value.substring(0, value.length() - 1); default -> { // 无后缀,优先参考变量类型 if (ctx.getVarType() != null) { String t = ctx.getVarType(); suffix = switch (t) { - case "byte" -> 'b'; - case "short" -> 's'; - case "int" -> 'i'; - case "long" -> 'l'; - case "float" -> 'f'; + case "byte" -> 'b'; + case "short" -> 's'; + case "int" -> 'i'; + case "long" -> 'l'; + case "float" -> 'f'; case "double" -> 'd'; - default -> '\0'; + default -> '\0'; }; } yield value; @@ -99,7 +104,7 @@ public final class ExpressionUtils { case 'l' -> new IRConstant(Long.parseLong(digits)); case 'f' -> new IRConstant(Float.parseFloat(digits)); case 'd' -> new IRConstant(Double.parseDouble(digits)); - default -> looksLikeFloat(digits) + default -> looksLikeFloat(digits) ? new IRConstant(Double.parseDouble(digits)) : new IRConstant(Integer.parseInt(digits)); }; @@ -121,7 +126,7 @@ public final class ExpressionUtils { case 'l' -> IROpCode.NEG_L64; case 'f' -> IROpCode.NEG_F32; case 'd' -> IROpCode.NEG_D64; - default -> IROpCode.NEG_I32; // 无法推断或为 int + default -> IROpCode.NEG_I32; // 无法推断或为 int }; } @@ -173,7 +178,7 @@ public final class ExpressionUtils { 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; + case 'b', 's', 'i', 'l', 'f', 'd' -> last; default -> looksLikeFloat(value) ? 'd' : '\0'; }; } @@ -236,7 +241,7 @@ public final class ExpressionUtils { case 'l' -> IROpCodeMappings.OP_L64; case 'f' -> IROpCodeMappings.OP_F32; case 'd' -> IROpCodeMappings.OP_D64; - default -> IROpCodeMappings.OP_I32; + default -> IROpCodeMappings.OP_I32; }; return table.get(op); } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/value/IRVirtualRegister.java b/src/main/java/org/jcnc/snow/compiler/ir/value/IRVirtualRegister.java index cb022f8e..942abc88 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/value/IRVirtualRegister.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/value/IRVirtualRegister.java @@ -8,13 +8,13 @@ import org.jcnc.snow.compiler.ir.core.IRValue; * 在 IR 系统中,虚拟寄存器用于存储每个中间计算结果,是 SSA(Static Single Assignment)形式的核心。 * 每个虚拟寄存器在程序中只被赋值一次,其值来源于一条明确的指令输出。 *

        - * 特点: + * 特点: *

          *
        • 每个寄存器有唯一编号 {@code id},由 {@code IRFunction.newRegister()} 自动生成
        • *
        • 实现 {@link IRValue} 接口,可作为 IRInstruction 的操作数
        • *
        • 具备良好的打印与调试格式: %id
        • *
        - * + *

        * 适用于表达式求值、参数传递、函数返回值、临时变量等所有中间值场景。 * * @param id 寄存器的唯一编号,通常从 0 开始递增 diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerContext.java b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerContext.java index 70cf64e0..8fbdcb5e 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerContext.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerContext.java @@ -21,19 +21,29 @@ public class LexerContext { /* ───────────────────────────────── 私有字段 ───────────────────────────────── */ - /** 源代码字符串(换行符已标准化为 \n) */ + /** + * 源代码字符串(换行符已标准化为 \n) + */ private final String source; - /** 当前扫描位置(自 0 起算的全局偏移量) */ + /** + * 当前扫描位置(自 0 起算的全局偏移量) + */ private int pos = 0; - /** 当前行号(从 1 开始) */ + /** + * 当前行号(从 1 开始) + */ private int line = 1; - /** 当前列号(从 1 开始) */ + /** + * 当前列号(从 1 开始) + */ private int col = 1; - /** 上一个字符对应的列号(用于异常定位) */ + /** + * 上一个字符对应的列号(用于异常定位) + */ private int lastCol = 1; /* ──────────────────────────────── 构造 & 基本信息 ─────────────────────────────── */ @@ -122,15 +132,31 @@ public class LexerContext { /* ──────────────────────────────── 坐标查询 ─────────────────────────────── */ - /** @return 当前行号 (1-based) */ - public int getLine() { return line; } + /** + * @return 当前行号 (1-based) + */ + public int getLine() { + return line; + } - /** @return 当前列号 (1-based) */ - public int getCol() { return col; } + /** + * @return 当前列号 (1-based) + */ + public int getCol() { + return col; + } - /** @return 上一个字符的列号 */ - public int getLastCol() { return lastCol; } + /** + * @return 上一个字符的列号 + */ + public int getLastCol() { + return lastCol; + } - /** @return 当前指针在源文件中的全局偏移 (0-based) */ - public int getPos() { return pos; } + /** + * @return 当前指针在源文件中的全局偏移 (0-based) + */ + public int getPos() { + return pos; + } } diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerEngine.java b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerEngine.java index 6b5c3ba5..0984c983 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerEngine.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexerEngine.java @@ -1,11 +1,9 @@ package org.jcnc.snow.compiler.lexer.core; -import org.jcnc.snow.common.SnowConfig; import org.jcnc.snow.compiler.lexer.base.TokenScanner; import org.jcnc.snow.compiler.lexer.scanners.*; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.lexer.token.TokenType; -import org.jcnc.snow.compiler.lexer.utils.TokenPrinter; import java.io.File; import java.util.ArrayList; diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexicalException.java b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexicalException.java index 1518a70c..757e3078 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/core/LexicalException.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/core/LexicalException.java @@ -10,29 +10,36 @@ package org.jcnc.snow.compiler.lexer.core; *

      • 完全禁止 Java 堆栈信息输出,使命令行输出保持整洁。
      • *
      *
      - * 例: 
      + * 例:
        *     Main.snow: 行 7, 列 20: 词法错误: 非法字符序列 '@'
        * 
      */ public class LexicalException extends RuntimeException { - /** 错误发生的行号(从1开始) */ + /** + * 错误发生的行号(从1开始) + */ private final int line; - /** 错误发生的列号(从1开始) */ + /** + * 错误发生的列号(从1开始) + */ private final int column; - /** 错误原因 */ + /** + * 错误原因 + */ private final String reason; /** * 构造词法异常 - * @param reason 错误原因(如: 非法字符描述) - * @param line 出错行号 - * @param column 出错列号 + * + * @param reason 错误原因(如: 非法字符描述) + * @param line 出错行号 + * @param column 出错列号 */ public LexicalException(String reason, int line, int column) { // 错误描述直接为 reason,禁止异常堆栈打印 super(reason, null, false, false); this.reason = reason; - this.line = line; + this.line = line; this.column = column; } @@ -40,23 +47,34 @@ public class LexicalException extends RuntimeException { * 屏蔽异常堆栈填充(始终不打印堆栈信息) */ @Override - public synchronized Throwable fillInStackTrace() { return this; } + public synchronized Throwable fillInStackTrace() { + return this; + } /** * 获取出错的行号 + * * @return 行号 */ - public int getLine() { return line; } + public int getLine() { + return line; + } /** * 获取出错的列号 + * * @return 列号 */ - public int getColumn() { return column; } + public int getColumn() { + return column; + } /** * 获取出错的描述 + * * @return 出错描述 */ - public String getReason() { return reason; } + public String getReason() { + return reason; + } } diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/AbstractTokenScanner.java b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/AbstractTokenScanner.java index a5397444..ac8ec112 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/AbstractTokenScanner.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/AbstractTokenScanner.java @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.lexer.scanners; -import org.jcnc.snow.compiler.lexer.core.LexerContext; import org.jcnc.snow.compiler.lexer.base.TokenScanner; +import org.jcnc.snow.compiler.lexer.core.LexerContext; import org.jcnc.snow.compiler.lexer.token.Token; import java.util.List; diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/SymbolTokenScanner.java b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/SymbolTokenScanner.java index 3810de8a..d4d51c40 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/SymbolTokenScanner.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/SymbolTokenScanner.java @@ -7,7 +7,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType; /** * 符号扫描器: 识别常见的单字符符号,如冒号、逗号、括号和算术符号。 *

      - * 支持的符号包括: + * 支持的符号包括: *

        *
      • 标点符号: : , .
      • *
      • 括号: ( )
      • diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/UnknownTokenScanner.java b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/UnknownTokenScanner.java index 6c91408b..9a21570b 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/scanners/UnknownTokenScanner.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/scanners/UnknownTokenScanner.java @@ -20,6 +20,7 @@ public class UnknownTokenScanner extends AbstractTokenScanner { /** * 判断是否可以处理当前字符。 * 对于 UnknownTokenScanner,始终返回 true(兜底扫描器,必须排在扫描器链末尾)。 + * * @param c 当前待处理字符 * @param ctx 词法上下文 * @return 是否处理该字符(始终为 true) @@ -32,7 +33,8 @@ public class UnknownTokenScanner extends AbstractTokenScanner { /** * 实际处理非法字符序列的方法。 * 连续读取所有无法被其他扫描器识别的字符,组成错误片段并抛出异常。 - * @param ctx 词法上下文 + * + * @param ctx 词法上下文 * @param line 错误发生行号 * @param col 错误发生列号 * @return 不会返回Token(始终抛异常) diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/Token.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/Token.java index 8dcdc656..3a8e81eb 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/Token.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/Token.java @@ -10,19 +10,29 @@ package org.jcnc.snow.compiler.lexer.token; */ public class Token { - /** Token 的类型,如 KEYWORD、IDENTIFIER、TYPE 等。 */ + /** + * Token 的类型,如 KEYWORD、IDENTIFIER、TYPE 等。 + */ private final TokenType type; - /** 清洗后的词素内容,例如去掉引号的字符串正文或注释正文。 */ + /** + * 清洗后的词素内容,例如去掉引号的字符串正文或注释正文。 + */ private final String lexeme; - /** 源代码中对应的原始片段,可能包含引号、注释符号等。 */ + /** + * 源代码中对应的原始片段,可能包含引号、注释符号等。 + */ private final String raw; - /** Token 在源文件中的行号,从 1 开始计数。 */ + /** + * Token 在源文件中的行号,从 1 开始计数。 + */ private final int line; - /** Token 在源文件行中的列号,从 1 开始计数。 */ + /** + * Token 在源文件行中的列号,从 1 开始计数。 + */ private final int col; /** @@ -70,27 +80,37 @@ public class Token { return new Token(TokenType.EOF, "", "", line, 1); } - /** @return 此 Token 的类型 */ + /** + * @return 此 Token 的类型 + */ public TokenType getType() { return type; } - /** @return 清洗后的词素内容(lexeme) */ + /** + * @return 清洗后的词素内容(lexeme) + */ public String getLexeme() { return lexeme; } - /** @return 源代码中的原始片段 */ + /** + * @return 源代码中的原始片段 + */ public String getRaw() { return raw; } - /** @return Token 所在的源文件行号(从 1 开始) */ + /** + * @return Token 所在的源文件行号(从 1 开始) + */ public int getLine() { return line; } - /** @return Token 所在行的列号(从 1 开始) */ + /** + * @return Token 所在行的列号(从 1 开始) + */ public int getCol() { return col; } diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java index 07b6561f..488ca398 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java @@ -11,101 +11,165 @@ package org.jcnc.snow.compiler.lexer.token; public enum TokenType { /* ---------- 基础 ---------- */ - /** 普通标识符,如变量名、函数名等 */ + /** + * 普通标识符,如变量名、函数名等 + */ IDENTIFIER, - /** 关键字(declare、if、else、loop、break、continue、return 等) */ + /** + * 关键字(declare、if、else、loop、break、continue、return 等) + */ KEYWORD, - /** 内置类型名(byte、short、int、long、float、double、string、boolean、void 等) */ + /** + * 内置类型名(byte、short、int、long、float、double、string、boolean、void 等) + */ TYPE, /* ---------- 字面量 ---------- */ - /** 布尔字面量 (true / false) */ + /** + * 布尔字面量 (true / false) + */ BOOL_LITERAL, - /** 字符串字面量(如 "hello") */ + /** + * 字符串字面量(如 "hello") + */ STRING_LITERAL, - /** 数字字面量(整数或浮点数) */ + /** + * 数字字面量(整数或浮点数) + */ NUMBER_LITERAL, /* ---------- 分隔符 ---------- */ - /** 冒号 ':' */ + /** + * 冒号 ':' + */ COLON, - /** 逗号 ',' */ + /** + * 逗号 ',' + */ COMMA, - /** 点号 '.' */ + /** + * 点号 '.' + */ DOT, /* ---------- 运算符 ---------- */ - /** 赋值符号 '=' */ + /** + * 赋值符号 '=' + */ EQUALS, - /** 取模运算符 '%' */ + /** + * 取模运算符 '%' + */ MODULO, - /** 加号 '+' */ + /** + * 加号 '+' + */ PLUS, - /** 乘号 '*' */ + /** + * 乘号 '*' + */ MULTIPLY, - /**除号 '/' */ + /** + * 除号 '/' + */ DIVIDE, - /** 减号 '-' */ + /** + * 减号 '-' + */ MINUS, - /** 取反 '!' */ + /** + * 取反 '!' + */ NOT, - /** 左括号 '(' */ + /** + * 左括号 '(' + */ LPAREN, - /** 右括号 ')' */ + /** + * 右括号 ')' + */ RPAREN, - /** 左中括号 '[' */ + /** + * 左中括号 '[' + */ LBRACKET, - /** 右中括号 ']' */ + /** + * 右中括号 ']' + */ RBRACKET, - /** 相等比较符号 '==' */ + /** + * 相等比较符号 '==' + */ DOUBLE_EQUALS, - /** 不等比较符号 '!=' */ + /** + * 不等比较符号 '!=' + */ NOT_EQUALS, - /** 大于符号 '>' */ + /** + * 大于符号 '>' + */ GREATER_THAN, - /** 大于等于符号 '>=' */ + /** + * 大于等于符号 '>=' + */ GREATER_EQUAL, - /** 小于符号 '<' */ + /** + * 小于符号 '<' + */ LESS_THAN, - /** 小于等于符号 '<=' */ + /** + * 小于等于符号 '<=' + */ LESS_EQUAL, - /** 逻辑与符号 '&&' */ + /** + * 逻辑与符号 '&&' + */ AND, - /** 逻辑或符号 '||' */ + /** + * 逻辑或符号 '||' + */ OR, - /** 换行符,标识逻辑换行 */ + /** + * 换行符,标识逻辑换行 + */ NEWLINE, - /** 单行或多行注释内容 */ + /** + * 单行或多行注释内容 + */ COMMENT, - /** 文件结束符(End of File) */ + /** + * 文件结束符(End of File) + */ EOF, - /** 无法识别的非法或未知符号 */ + /** + * 无法识别的非法或未知符号 + */ UNKNOWN } \ No newline at end of file diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/utils/TokenPrinter.java b/src/main/java/org/jcnc/snow/compiler/lexer/utils/TokenPrinter.java index 0935b48b..6418db1f 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/utils/TokenPrinter.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/utils/TokenPrinter.java @@ -17,7 +17,7 @@ public class TokenPrinter { /** * 将给定的 Token 列表打印到标准输出(控制台)。 *

        - * 输出格式: + * 输出格式: *

              * line   col    type             lexeme
              * ----------------------------------------------------
        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 34b387c0..c4384c6e 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
        @@ -1,8 +1,8 @@
         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 org.jcnc.snow.compiler.parser.ast.base.StatementNode;
         
         /**
          * {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。
        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 af2cdae6..52a005e3 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
        @@ -1,8 +1,8 @@
         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 org.jcnc.snow.compiler.parser.ast.base.StatementNode;
         
         import java.util.Optional;
         
        @@ -14,13 +14,19 @@ import java.util.Optional;
          */
         public class DeclarationNode implements StatementNode {
         
        -    /** 声明的变量名称。 */
        +    /**
        +     * 声明的变量名称。
        +     */
             private final String name;
         
        -    /** 变量的数据类型(如 "int", "string")。 */
        +    /**
        +     * 变量的数据类型(如 "int", "string")。
        +     */
             private final String type;
         
        -    /** 是否为常量声明(true 表示 const 变量,false 表示普通变量)。 */
        +    /**
        +     * 是否为常量声明(true 表示 const 变量,false 表示普通变量)。
        +     */
             private final boolean isConst;
         
             /**
        @@ -29,7 +35,9 @@ public class DeclarationNode implements StatementNode {
              */
             private final Optional initializer;
         
        -    /** 节点上下文信息(如源码中的行号、列号等)。 */
        +    /**
        +     * 节点上下文信息(如源码中的行号、列号等)。
        +     */
             private final NodeContext context;
         
             /**
        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 7a52cc42..8adb78ad 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
        @@ -1,8 +1,8 @@
         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 org.jcnc.snow.compiler.parser.ast.base.StatementNode;
         
         /**
          * {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。
        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 ecc0dd10..6490e61c 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
        @@ -1,8 +1,8 @@
         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 org.jcnc.snow.compiler.parser.ast.base.StatementNode;
         
         import java.util.List;
         
        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 ab4bb90b..8131d38b 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
        @@ -6,7 +6,7 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
         /**
          * {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。
          * 

        - * import 语句用于引入外部模块或库文件,其语法形式一般为: + * import 语句用于引入外部模块或库文件,其语法形式一般为: * {@code import my.module;} *

        *

        diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/IndexExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/IndexExpressionNode.java index a33caa90..fc67ae53 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/IndexExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/IndexExpressionNode.java @@ -32,6 +32,7 @@ public record IndexExpressionNode( /** * 返回形如 "arr[i]" 的字符串表示。 + * * @return 表达式的字符串形式 */ @Override 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 8ab233bf..b9c56340 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 @@ -10,9 +10,9 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext; * 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。 *

        * - * @param object 左侧对象表达式,表示成员所属的作用域或容器 - * @param member 要访问的成员名称(字段名或方法名) - * @param context 节点上下文信息(包含行号、列号等) + * @param object 左侧对象表达式,表示成员所属的作用域或容器 + * @param member 要访问的成员名称(字段名或方法名) + * @param context 节点上下文信息(包含行号、列号等) */ public record MemberExpressionNode( ExpressionNode object, 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 836c547b..9924f462 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 @@ -38,7 +38,7 @@ public record ModuleNode( * 列出模块名、导入、全局变量、结构体、函数等简明内容。 * * @return 字符串形式,如 - * Module(name=main, imports=[math], globals=[int x], structs=[Foo], functions=[bar]) + * Module(name=main, imports=[math], globals=[int x], structs=[Foo], functions=[bar]) */ @Override public String toString() { @@ -59,10 +59,10 @@ public record ModuleNode( functions.forEach(f -> funcJ.add(f.name())); // 5) 综合输出 - return "Module(name=" + name + - ", imports=[" + impJ + "]" + - ", globals=[" + globJ + "]" + - ", structs=[" + structJ + "]" + - ", functions=[" + funcJ + "])"; + return "Module(name=" + name + + ", imports=[" + impJ + "]" + + ", globals=[" + globJ + "]" + + ", structs=[" + structJ + "]" + + ", functions=[" + funcJ + "])"; } } 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 6806112d..f0d6beb1 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 @@ -11,8 +11,8 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext; * 在语义分析或类型推导阶段再行解析为具体数值类型。 *

        * - * @param value 数字字面量的原始字符串表示 - * @param context 节点上下文信息(包含行号、列号等) + * @param value 数字字面量的原始字符串表示 + * @param context 节点上下文信息(包含行号、列号等) */ public record NumberLiteralNode( String value, 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 15d6297e..eeb18eab 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 @@ -1,8 +1,8 @@ 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 org.jcnc.snow.compiler.parser.ast.base.StatementNode; import java.util.Optional; @@ -12,7 +12,7 @@ import java.util.Optional; * return 语句用于从当前函数中返回控制权,并可携带一个可选的返回值表达式。 *

        *

        - * 示例: + * 示例: *

          *
        • {@code return;}
        • *
        • {@code return x + 1;}
        • @@ -21,10 +21,14 @@ import java.util.Optional; */ public class ReturnNode implements StatementNode { - /** 可选的返回值表达式 */ + /** + * 可选的返回值表达式 + */ private final Optional expression; - /** 节点上下文信息(包含行号、列号等) */ + /** + * 节点上下文信息(包含行号、列号等) + */ private final NodeContext context; /** 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 dd0e61fc..9f264231 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 @@ -10,8 +10,8 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext; * 节点内部仅保存不带引号的字符串内容,便于后续语义处理或编码。 *

          * - * @param value 字符串常量的内容,原始值中不包含双引号 - * @param context 节点上下文信息(包含行号、列号等) + * @param value 字符串常量的内容,原始值中不包含双引号 + * @param context 节点上下文信息(包含行号、列号等) */ public record StringLiteralNode( String value, diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/StructNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StructNode.java index b5581575..81bd10ae 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StructNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StructNode.java @@ -20,7 +20,7 @@ import java.util.StringJoiner; * @param name 结构体名称 * @param parent 父类名称(无继承时为 {@code null}) * @param fields 字段声明列表 - * @param inits 构造函数(可为 null) + * @param inits 构造函数(可为 null) * @param methods 方法列表 * @param context 源码位置信息 */ 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 c30d7ed2..4111f759 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 @@ -6,12 +6,12 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext; /** * {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。 * - *

          代表两种受支持的一元前缀表达式: + *

          代表两种受支持的一元前缀表达式: *

            *
          • 取负: {@code -x}
          • *
          • 逻辑非: {@code !x}
          • *
          - * + *

          * {@link #equals(Object)}、{@link #hashCode()} 等方法。

          * * @param operator 一元运算符(仅 "-" 或 "!") diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/ExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/ExpressionNode.java index e8db6452..52949231 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/ExpressionNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/ExpressionNode.java @@ -11,4 +11,5 @@ package org.jcnc.snow.compiler.parser.ast.base; * 所有实现此接口的节点可参与表达式求值、语义分析、类型检查与中间代码生成等处理流程。 *

          */ -public interface ExpressionNode extends Node {} \ No newline at end of file +public interface ExpressionNode extends Node { +} \ No newline at end of file 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 e5d33eb8..794e3780 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 @@ -4,7 +4,7 @@ package org.jcnc.snow.compiler.parser.ast.base; * {@code Node} 是抽象语法树(AST)中所有语法节点的统一根接口。 *

          * 作为标记接口(Marker Interface),该接口定义 3 个方法: line()、column() 和 file() 用于定位错误, - * 主要用于统一标识并组织 AST 体系中的各种语法构件节点,包括: + * 主要用于统一标识并组织 AST 体系中的各种语法构件节点,包括: *

          *
            *
          • {@link ExpressionNode}: 表达式节点,如常量、变量引用、函数调用等
          • diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/StatementNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/StatementNode.java index b4db2cb3..f1dbee85 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ast/base/StatementNode.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/base/StatementNode.java @@ -8,4 +8,5 @@ package org.jcnc.snow.compiler.parser.ast.base; * 实现此接口的类应表示程序在运行时执行的具体语法行为。 *

            */ -public interface StatementNode extends Node {} +public interface StatementNode extends Node { +} diff --git a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseError.java b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseError.java index c32d95ea..af906d80 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseError.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseError.java @@ -9,13 +9,21 @@ package org.jcnc.snow.compiler.parser.context; */ public class ParseError { - /** 出错的文件名 */ + /** + * 出错的文件名 + */ private final String file; - /** 出错的行号 */ + /** + * 出错的行号 + */ private final int line; - /** 出错的列号 */ + /** + * 出错的列号 + */ private final int column; - /** 错误信息描述 */ + /** + * 错误信息描述 + */ private final String message; /** @@ -27,9 +35,9 @@ public class ParseError { * @param message 错误信息描述 */ public ParseError(String file, int line, int column, String message) { - this.file = file; - this.line = line; - this.column = column; + this.file = file; + this.line = line; + this.column = column; this.message = message; } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java index 97ceb330..7c7b09e5 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java @@ -14,25 +14,31 @@ package org.jcnc.snow.compiler.parser.context; public sealed class ParseException extends RuntimeException permits MissingToken, UnexpectedToken, UnsupportedFeature { - /** 出错行号(从 1 开始) */ + /** + * 出错行号(从 1 开始) + */ private final int line; - /** 出错列号(从 1 开始) */ + /** + * 出错列号(从 1 开始) + */ private final int column; - /** 错误原因描述 */ + /** + * 错误原因描述 + */ private final String reason; /** * 构造语法分析异常。 * - * @param reason 错误原因描述 - * @param line 出错行号(从 1 开始) - * @param column 出错列号(从 1 开始) + * @param reason 错误原因描述 + * @param line 出错行号(从 1 开始) + * @param column 出错列号(从 1 开始) */ public ParseException(String reason, int line, int column) { // 禁用 cause / suppression / stackTrace,确保 CLI 输出简洁 super(reason, null, false, false); this.reason = reason; - this.line = line; + this.line = line; this.column = column; } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/ArrayLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/ArrayLiteralParselet.java index 6a9a483b..e46d2e5f 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/ArrayLiteralParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/ArrayLiteralParselet.java @@ -25,6 +25,17 @@ import java.util.List; */ public class ArrayLiteralParselet implements PrefixParselet { + /** + * 跳过词法流中连续的换行符,允许数组元素跨多行书写。 + * + * @param ts 词法流 + */ + private static void skipNewlines(TokenStream ts) { + while (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + } + } + /** * 解析数组字面量表达式。 * @@ -36,7 +47,7 @@ public class ArrayLiteralParselet implements PrefixParselet { public ExpressionNode parse(ParserContext ctx, Token token) { // token 为已消费的 LBRACKET,使用其位置生成 NodeContext int line = token.getLine(); - int col = token.getCol(); + int col = token.getCol(); String file = ctx.getSourceName(); TokenStream ts = ctx.getTokens(); @@ -66,15 +77,4 @@ public class ArrayLiteralParselet implements PrefixParselet { ts.expectType(TokenType.RBRACKET); return new ArrayLiteralNode(elements, new NodeContext(line, col, file)); } - - /** - * 跳过词法流中连续的换行符,允许数组元素跨多行书写。 - * - * @param ts 词法流 - */ - private static void skipNewlines(TokenStream ts) { - while (ts.peek().getType() == TokenType.NEWLINE) { - ts.next(); - } - } } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java index 3fa483c1..62dd5c1f 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java @@ -48,19 +48,19 @@ public class PrattExpressionParser implements ExpressionParser { // ----------------- 前缀解析器注册 ----------------- // 各种字面量/标识符 prefixes.put(TokenType.NUMBER_LITERAL.name(), new NumberLiteralParselet()); - prefixes.put(TokenType.IDENTIFIER.name(), new IdentifierParselet()); + prefixes.put(TokenType.IDENTIFIER.name(), new IdentifierParselet()); prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet()); - prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet()); + prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet()); // 分组与数组字面量(两种索引方式) - prefixes.put(TokenType.LPAREN.name(), new GroupingParselet()); + prefixes.put(TokenType.LPAREN.name(), new GroupingParselet()); prefixes.put(TokenType.LBRACKET.name(), new ArrayLiteralParselet()); prefixes.put("(", new GroupingParselet()); prefixes.put("[", new ArrayLiteralParselet()); // 一元前缀运算符(如负号、逻辑非),同样用两种方式注册 prefixes.put(TokenType.MINUS.name(), new UnaryOperatorParselet()); - prefixes.put(TokenType.NOT.name(), new UnaryOperatorParselet()); + prefixes.put(TokenType.NOT.name(), new UnaryOperatorParselet()); prefixes.put("-", new UnaryOperatorParselet()); prefixes.put("!", new UnaryOperatorParselet()); @@ -69,14 +69,14 @@ public class PrattExpressionParser implements ExpressionParser { // ----------------- 中缀解析器注册 ----------------- // 常见二元算数运算符 - infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true)); - infixes.put("-", new BinaryOperatorParselet(Precedence.SUM, true)); - infixes.put("*", new BinaryOperatorParselet(Precedence.PRODUCT, true)); - infixes.put("/", new BinaryOperatorParselet(Precedence.PRODUCT, true)); - infixes.put("%", new BinaryOperatorParselet(Precedence.PRODUCT, true)); + infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true)); + infixes.put("-", new BinaryOperatorParselet(Precedence.SUM, true)); + infixes.put("*", new BinaryOperatorParselet(Precedence.PRODUCT, true)); + infixes.put("/", new BinaryOperatorParselet(Precedence.PRODUCT, true)); + infixes.put("%", new BinaryOperatorParselet(Precedence.PRODUCT, true)); // 比较运算符 - infixes.put(">", new BinaryOperatorParselet(Precedence.COMPARISON, true)); - infixes.put("<", new BinaryOperatorParselet(Precedence.COMPARISON, true)); + infixes.put(">", new BinaryOperatorParselet(Precedence.COMPARISON, true)); + infixes.put("<", new BinaryOperatorParselet(Precedence.COMPARISON, true)); infixes.put(">=", new BinaryOperatorParselet(Precedence.COMPARISON, true)); infixes.put("<=", new BinaryOperatorParselet(Precedence.COMPARISON, true)); // 相等性判断 @@ -84,7 +84,7 @@ public class PrattExpressionParser implements ExpressionParser { infixes.put("!=", new BinaryOperatorParselet(Precedence.EQUALITY, true)); // 逻辑运算 infixes.put("&&", new BinaryOperatorParselet(Precedence.AND, true)); - infixes.put("||", new BinaryOperatorParselet(Precedence.OR, true)); + infixes.put("||", new BinaryOperatorParselet(Precedence.OR, true)); // 函数调用、数组下标、成员访问 infixes.put("(", new CallParselet()); infixes.put("[", new IndexParselet()); diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java index e47a5aa6..0d818842 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java @@ -9,30 +9,48 @@ package org.jcnc.snow.compiler.parser.expression; */ public enum Precedence { - /** 最低优先级,通常用于整个表达式解析的起始入口。 */ + /** + * 最低优先级,通常用于整个表达式解析的起始入口。 + */ LOWEST, - /** 逻辑或(||) */ + /** + * 逻辑或(||) + */ OR, - /** 逻辑与(&&) */ + /** + * 逻辑与(&&) + */ AND, - /** 相等/不等(==, !=) */ + /** + * 相等/不等(==, !=) + */ EQUALITY, - /** 大小比较(<, >, <=, >=) */ + /** + * 大小比较(<, >, <=, >=) + */ COMPARISON, - /** 加法和减法(+、-) */ + /** + * 加法和减法(+、-) + */ SUM, - /** 乘法、除法、取模(*、/、%) */ + /** + * 乘法、除法、取模(*、/、%) + */ PRODUCT, - /** 一元前缀(-x !x) */ + /** + * 一元前缀(-x !x) + */ UNARY, - /** 函数调用、成员访问等最强绑定(foo()、obj.prop) */ + /** + * 函数调用、成员访问等最强绑定(foo()、obj.prop) + */ CALL } 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 b4d417c1..77e7a340 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 @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.parser.expression; import org.jcnc.snow.common.StringEscape; 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.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; 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 00382b34..954790e0 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 @@ -10,12 +10,12 @@ import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; /** * {@code UnaryOperatorParselet} —— 前缀一元运算符的 Pratt 解析器。 * - *

            当前 parselet 负责解析两种前缀运算: + *

            当前 parselet 负责解析两种前缀运算: *

              *
            • 取负: {@code -x}
            • *
            • 逻辑非: {@code !x}
            • *
            - * + *

            * 解析过程: * *

              @@ -25,7 +25,7 @@ import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; *
            1. 最终生成 {@link UnaryExpressionNode} AST 节点,记录运算符与操作数。
            2. *
            * - *

            此类仅负责语法结构的构建: + *

            此类仅负责语法结构的构建: *

              *
            • 类型正确性在 {@code UnaryExpressionAnalyzer} 中校验;
            • *
            • IR 生成在 {@code ExpressionBuilder.buildUnary} 中完成。
            • @@ -38,7 +38,7 @@ public class UnaryOperatorParselet implements PrefixParselet { * * @param ctx 当前解析上下文 * @param token 已被消费的运算符 Token(字面值应为 {@code "-" 或 "!"}) - * @return 构建出的 {@link UnaryExpressionNode} + * @return 构建出的 {@link UnaryExpressionNode} */ @Override public ExpressionNode parse(ParserContext ctx, Token token) { diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/ExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/ExpressionParser.java index fd388fd6..6ce6614d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/ExpressionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/ExpressionParser.java @@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.parser.context.ParserContext; * 构建一个有效的 {@link ExpressionNode} 抽象语法树结构。 *

              *

              - * 不同的实现可以采用不同的解析技术: + * 不同的实现可以采用不同的解析技术: *

                *
              • 递归下降(Recursive Descent)
              • *
              • Pratt Parser(前缀/中缀优先级驱动)
              • diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/InfixParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/InfixParselet.java index 7ced99b9..c9365900 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/InfixParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/InfixParselet.java @@ -11,7 +11,7 @@ import org.jcnc.snow.compiler.parser.expression.Precedence; * 是 Pratt 解析器架构中处理中缀操作的关键组件。 *

                *

                - * 每个中缀解析器负责: + * 每个中缀解析器负责: *

                  *
                • 根据左侧已解析的表达式,结合当前运算符继续解析右侧部分
                • *
                • 提供运算符优先级,用于判断是否继续嵌套解析
                • diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/PrefixParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/PrefixParselet.java index 0864edae..73563092 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/base/PrefixParselet.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/base/PrefixParselet.java @@ -1,8 +1,8 @@ package org.jcnc.snow.compiler.parser.expression.base; +import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.context.ParserContext; -import org.jcnc.snow.compiler.lexer.token.Token; /** * {@code PrefixParselet} 是用于解析前缀表达式的通用接口。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java b/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java index 640db1bb..f8f1396d 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.parser.factory; import org.jcnc.snow.compiler.parser.statement.*; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * {@code StatementParserFactory} 是一个语句解析器工厂类, @@ -18,20 +18,22 @@ import java.util.HashMap; */ public class StatementParserFactory { - /** 注册表: 语句关键字 -> 对应语句解析器 */ + /** + * 注册表: 语句关键字 -> 对应语句解析器 + */ private static final Map registry = new HashMap<>(); static { // 注册各类语句解析器 registry.put("declare", new DeclarationStatementParser()); - registry.put("if", new IfStatementParser()); - registry.put("loop", new LoopStatementParser()); - registry.put("return", new ReturnStatementParser()); - registry.put("break", new BreakStatementParser()); - registry.put("continue",new ContinueStatementParser()); + registry.put("if", new IfStatementParser()); + registry.put("loop", new LoopStatementParser()); + registry.put("return", new ReturnStatementParser()); + registry.put("break", new BreakStatementParser()); + registry.put("continue", new ContinueStatementParser()); // 默认处理器: 表达式语句 - registry.put("", new ExpressionStatementParser()); + registry.put("", new ExpressionStatementParser()); } /** diff --git a/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java b/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java index eb838bef..7b189e7b 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java @@ -1,12 +1,12 @@ package org.jcnc.snow.compiler.parser.factory; import org.jcnc.snow.compiler.parser.base.TopLevelParser; -import org.jcnc.snow.compiler.parser.module.ModuleParser; import org.jcnc.snow.compiler.parser.function.FunctionParser; +import org.jcnc.snow.compiler.parser.module.ModuleParser; import org.jcnc.snow.compiler.parser.top.ScriptTopLevelParser; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * {@code TopLevelParserFactory} 用于根据源码中顶层关键字取得对应的解析器。 @@ -15,15 +15,19 @@ import java.util.HashMap; */ public class TopLevelParserFactory { - /** 关键字 → 解析器注册表 */ + /** + * 关键字 → 解析器注册表 + */ private static final Map registry = new HashMap<>(); - /** 缺省解析器: 脚本模式(单条语句可执行) */ + /** + * 缺省解析器: 脚本模式(单条语句可执行) + */ private static final TopLevelParser DEFAULT = new ScriptTopLevelParser(); static { // 在此注册所有受支持的顶层结构关键字 - registry.put("module", new ModuleParser()); + registry.put("module", new ModuleParser()); registry.put("function", new FunctionParser()); // 若未来新增顶层结构,可继续在此处注册 } 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 d46abd32..722cce5e 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,9 +1,9 @@ package org.jcnc.snow.compiler.parser.module; import org.jcnc.snow.compiler.lexer.token.TokenType; +import org.jcnc.snow.compiler.parser.ast.ImportNode; 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; import java.util.ArrayList; import java.util.List; 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 4a9d3df3..354000d9 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 @@ -30,7 +30,7 @@ public class DeclarationStatementParser implements StatementParser { var tokens = ctx.getTokens(); // 获取词法单元流 // 记录声明语句在源码中的位置信息(行、列、文件名) - int line = tokens.peek().getLine(); + int line = tokens.peek().getLine(); int column = tokens.peek().getCol(); String file = ctx.getSourceName(); 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 766f53d4..774c10bd 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 @@ -20,7 +20,7 @@ import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; * doSomething() // 一般表达式语句 * this.name = n // 将 this.name 赋值语法糖为对 name 的赋值 * }
        - * + *

        * - 以标识符开头且后接 '=' 时,解析为 {@link AssignmentNode}。 * - 否则先解析为一般表达式;若后续遇到 '=',则回退为“ = ”赋值语句。 * - 所有表达式语句必须以换行符(NEWLINE)结尾。 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 aaff6126..6d38528b 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 @@ -15,7 +15,7 @@ import java.util.List; /** * {@code IfStatementParser} 类负责解析 if 条件语句,是语句级解析器中的条件分支处理器。 *

        - * 本解析器支持以下结构的条件语法: + * 本解析器支持以下结构的条件语法: *

        {@code
          * if  then
          *     
        @@ -23,7 +23,7 @@ import java.util.List;
          *     ]
          * end if
          * }
        - * 其中: + * 其中: *
          *
        • {@code } 为任意可解析的布尔或数值表达式,使用 {@link PrattExpressionParser} 解析;
        • *
        • {@code } 与 {@code } 可包含多条语句,自动跳过空行;
        • 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 76bb621e..b3f6348a 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 @@ -2,8 +2,8 @@ package org.jcnc.snow.compiler.parser.statement; 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.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; @@ -21,7 +21,7 @@ import java.util.Map; /** * {@code LoopStatementParser} 类负责解析自定义结构化的 {@code loop} 语句块。 *

          - * 该语法结构参考了传统的 for-loop,并将其拆解为命名的语义区块: + * 该语法结构参考了传统的 for-loop,并将其拆解为命名的语义区块: *

          {@code
            * loop:
            *     init:
          @@ -35,8 +35,8 @@ import java.util.Map;
            *     end body
            * end loop
            * }
          - * - * 各区块说明: + *

          + * 各区块说明: *

            *
          • {@code init}: 初始化语句,通常为变量声明。
          • *
          • {@code cond}: 循环判断条件,必须为布尔或数值表达式。
          • @@ -50,7 +50,7 @@ public class LoopStatementParser implements StatementParser { /** * 解析 {@code loop} 语句块,构建出对应的 {@link LoopNode} 抽象语法树节点。 *

            - * 本方法会按顺序检查各个命名区块(可乱序书写),并分别绑定其对应语义解析器: + * 本方法会按顺序检查各个命名区块(可乱序书写),并分别绑定其对应语义解析器: *

              *
            • 通过 {@link ParserUtils#matchHeader} 匹配区块开头;
            • *
            • 通过 {@link FlexibleSectionParser} 派发区块逻辑;
            • 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 f344b80c..146dafda 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 @@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser; /** * {@code ReturnStatementParser} 负责解析 return 语句,是语句级解析器的一部分。 *

              - * 支持以下两种 return 语句形式: + * 支持以下两种 return 语句形式: *

              {@code
                * return             // 无返回值
                * return expression  // 带返回值
              @@ -23,7 +23,7 @@ public class ReturnStatementParser implements StatementParser {
                   /**
                    * 解析一条 return 语句,并返回对应的 {@link ReturnNode} 抽象语法树节点。
                    * 

              - * 解析逻辑如下: + * 解析逻辑如下: *

                *
              1. 匹配起始关键字 {@code return}。
              2. *
              3. 判断其后是否为 {@code NEWLINE},若否则表示存在返回值表达式。
              4. diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java index edcc075c..45403bbb 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.parser.statement; -import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.context.ParserContext; /** * {@code StatementParser} 是所有语句解析器的通用接口。 diff --git a/src/main/java/org/jcnc/snow/compiler/parser/top/ScriptTopLevelParser.java b/src/main/java/org/jcnc/snow/compiler/parser/top/ScriptTopLevelParser.java index 3403dcfa..0c88168c 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/top/ScriptTopLevelParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/top/ScriptTopLevelParser.java @@ -1,8 +1,8 @@ package org.jcnc.snow.compiler.parser.top; -import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.ast.base.Node; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.base.TopLevelParser; import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.factory.StatementParserFactory; import org.jcnc.snow.compiler.parser.statement.StatementParser; diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/FlexibleSectionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/FlexibleSectionParser.java index 04aeadc6..c0f71391 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/FlexibleSectionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/FlexibleSectionParser.java @@ -18,7 +18,7 @@ import java.util.function.Predicate; *

                * *

                - * 典型用途包括: + * 典型用途包括: *

                  *
                • 函数体解析中的 {@code params}、{@code returns}、{@code body} 等部分
                • *
                • 模块定义中的 {@code imports}、{@code functions} 等部分
                • @@ -42,7 +42,7 @@ public class FlexibleSectionParser { * @param ctx 解析上下文 * @param tokens 词法流 * @param sectionDefinitions 区块处理注册表,key 为区块关键字,value 为对应的处理定义 - * @throws UnexpectedToken 遇到未注册或条件不符的关键字时抛出 + * @throws UnexpectedToken 遇到未注册或条件不符的关键字时抛出 */ public static void parse(ParserContext ctx, TokenStream tokens, diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/JSONParser.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/JSONParser.java index 84d18239..88e2d230 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/JSONParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/JSONParser.java @@ -25,7 +25,8 @@ import java.util.Map.Entry; */ public class JSONParser { - private JSONParser() {} + private JSONParser() { + } /** * 解析 JSON 格式字符串为对应的 Java 对象。 @@ -170,21 +171,29 @@ public class JSONParser { c = currentChar(); switch (c) { case '"': - sb.append('"'); break; + sb.append('"'); + break; case '\\': - sb.append('\\'); break; + sb.append('\\'); + break; case '/': - sb.append('/'); break; + sb.append('/'); + break; case 'b': - sb.append('\b'); break; + sb.append('\b'); + break; case 'f': - sb.append('\f'); break; + sb.append('\f'); + break; case 'n': - sb.append('\n'); break; + sb.append('\n'); + break; case 'r': - sb.append('\r'); break; + sb.append('\r'); + break; case 't': - sb.append('\t'); break; + sb.append('\t'); + break; case 'u': String hex = new String(buf, pos + 1, 4); sb.append((char) Integer.parseInt(hex, 16)); @@ -211,7 +220,9 @@ public class JSONParser { if (currentChar() == '-') advance(); while (isDigit(currentChar())) advance(); if (currentChar() == '.') { - do { advance(); } while (isDigit(currentChar())); + do { + advance(); + } while (isDigit(currentChar())); } if (currentChar() == 'e' || currentChar() == 'E') { advance(); @@ -253,7 +264,8 @@ public class JSONParser { private void advance() { if (pos < buf.length) { if (buf[pos] == '\n') { - line++; col = 1; + line++; + col = 1; } else { col++; } @@ -358,15 +370,20 @@ public class JSONParser { for (char c : s.toCharArray()) { switch (c) { case '\\': - sb.append("\\\\"); break; + sb.append("\\\\"); + break; case '"': - sb.append("\\\""); break; + sb.append("\\\""); + break; case '\n': - sb.append("\\n"); break; + sb.append("\\n"); + break; case '\r': - sb.append("\\r"); break; + sb.append("\\r"); + break; case '\t': - sb.append("\\t"); break; + sb.append("\\t"); + break; default: sb.append(c); } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/JsonFormatter.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/JsonFormatter.java index 02eb3055..d41b35d9 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/JsonFormatter.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/JsonFormatter.java @@ -8,7 +8,7 @@ public class JsonFormatter { /** * 对一个紧凑的 JSON 字符串进行缩进美化。 - * 例如: + * 例如: *
                  {@code
                        * {"a":1,"b":[2,3]} →
                        * {
                  diff --git a/src/main/java/org/jcnc/snow/compiler/parser/utils/ParserUtils.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/ParserUtils.java
                  index cce7a9a7..5c1ec5be 100644
                  --- a/src/main/java/org/jcnc/snow/compiler/parser/utils/ParserUtils.java
                  +++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/ParserUtils.java
                  @@ -9,7 +9,7 @@ import org.jcnc.snow.compiler.parser.context.TokenStream;
                    * 提供一系列静态方法用于标准语法结构(如结构头、结构尾)的匹配校验,以及常用的容错处理操作。
                    * 这些方法可在函数定义、模块定义、循环、条件语句等语法块中复用,有效减少冗余代码,提高解析器稳定性。
                    *
                  - * 

                  主要功能包括: + *

                  主要功能包括: *

                    *
                  • 匹配结构性语法起始标记(如 {@code loop:}、{@code function:})
                  • *
                  • 匹配结构性语法结尾标记(如 {@code end loop}、{@code end function})
                  • diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/base/ExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/base/ExpressionAnalyzer.java index bc018892..7274461e 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/base/ExpressionAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/base/ExpressionAnalyzer.java @@ -34,7 +34,7 @@ public interface ExpressionAnalyzer { * @param fn 当前函数节点,可用于返回类型校验或其他函数级上下文 * @param locals 当前作用域的符号表,包含已声明的变量及其类型 * @param expr 待分析的表达式节点 - * @return 表达式的推导类型,用于后续类型兼容性检查和类型传播 + * @return 表达式的推导类型,用于后续类型兼容性检查和类型传播 */ Type analyze(Context ctx, ModuleInfo mi, diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BinaryExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BinaryExpressionAnalyzer.java index 672bc474..a677ed0d 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BinaryExpressionAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BinaryExpressionAnalyzer.java @@ -13,7 +13,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; /** * {@code BinaryExpressionAnalyzer} 负责对二元表达式做语义分析并返回其类型。 *

                    - * 支持特性: + * 支持特性: * 1. 字符串拼接「+」 * 2. 数值运算与自动宽化 * 3. 比较 / 关系运算 @@ -34,7 +34,7 @@ public class BinaryExpressionAnalyzer implements ExpressionAnalyzer * 它的主要职责是在给定的局部作用域中查找标识符对应的符号定义,并返回其类型信息。 - * 如果标识符未在当前作用域内声明,则: + * 如果标识符未在当前作用域内声明,则: *

                      *
                    • 向语义错误列表中添加一条 {@link SemanticError} 记录;
                    • *
                    • 为保证分析过程的连续性,默认返回 {@link BuiltinType#INT} 类型作为降级处理。
                    • @@ -34,7 +34,7 @@ public class IdentifierAnalyzer implements ExpressionAnalyzer { * @param locals 当前函数或代码块的符号表,记录已声明的变量及其类型信息。 * @param id 表达式中出现的 {@link IdentifierNode} 实例,表示待解析的标识符名称。 * @return 若标识符已在符号表中声明,则返回对应的 {@link Type}; - * 否则返回 {@link BuiltinType#INT} 作为错误降级类型。 + * 否则返回 {@link BuiltinType#INT} 作为错误降级类型。 */ @Override public Type analyze(Context ctx, diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/NewExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/NewExpressionAnalyzer.java index 3b44e79a..8bf3617e 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/NewExpressionAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/NewExpressionAnalyzer.java @@ -95,7 +95,7 @@ public class NewExpressionAnalyzer implements ExpressionAnalyzer expectedParams = ctor.paramTypes(); for (int i = 0; i < expectedParams.size(); i++) { Type expected = expectedParams.get(i); // 构造函数声明的参数类型 - Type actual = argTypes.get(i); // 实际传入的实参类型 + Type actual = argTypes.get(i); // 实际传入的实参类型 boolean compatible = expected.isCompatible(actual); // 直接类型兼容 boolean widenOK = expected.isNumeric() diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/StringLiteralAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/StringLiteralAnalyzer.java index 86412e5a..151b7d76 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/StringLiteralAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/StringLiteralAnalyzer.java @@ -1,7 +1,7 @@ package org.jcnc.snow.compiler.semantic.analyzers.expression; -import org.jcnc.snow.compiler.parser.ast.StringLiteralNode; import org.jcnc.snow.compiler.parser.ast.FunctionNode; +import org.jcnc.snow.compiler.parser.ast.StringLiteralNode; 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; diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java index b5d5217c..8ee4ecec 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java @@ -13,16 +13,16 @@ import org.jcnc.snow.compiler.semantic.type.Type; /** * {@code UnaryExpressionAnalyzer} — 一元表达式的语义分析器。 * - *

                      目前实现两种一元运算: + *

                      目前实现两种一元运算: *

                        *
                      • {@code -x} 取负: 仅允许作用于数值类型(int / float 等)。
                      • *
                      • {@code !x} 逻辑非: 仅允许作用于 {@code boolean} 类型。
                      • *
                      * - *

                      分析流程: + *

                      分析流程: *

                        *
                      1. 递归分析操作数表达式,获取其类型 {@code operandType}。
                      2. - *
                      3. 根据运算符检查类型合法性: + *
                      4. 根据运算符检查类型合法性: *
                          *
                        • 若类型不符,记录 {@link SemanticError} 并返回一个占位类型 * (取负返回 {@link BuiltinType#INT},逻辑非返回 diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java index 2ad7232e..583dba4e 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java @@ -20,12 +20,14 @@ import org.jcnc.snow.compiler.semantic.type.Type; *
                        • 常量保护:禁止修改 {@link SymbolKind#CONSTANT};
                        • *
                        • 类型兼容:验证右值类型与目标类型兼容,若均为数值类型则允许宽化转换(如 int → double)。
                        • *
                        - * + *

                        * 任何不满足条件的情况都会向 {@link Context#getErrors()} 记录 {@link SemanticError}。 */ public class AssignmentAnalyzer implements StatementAnalyzer { - /** 错误消息前缀,统一便于搜索定位 */ + /** + * 错误消息前缀,统一便于搜索定位 + */ private static final String ERR_PREFIX = "赋值错误: "; /** diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/DeclarationAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/DeclarationAnalyzer.java index 4a830fb8..7f1a0baa 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/DeclarationAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/DeclarationAnalyzer.java @@ -15,7 +15,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; /** * {@code DeclarationAnalyzer} 是变量声明语句的语义分析器。 *

                        - * 它负责处理类似 {@code int x = 10;} 的声明语句,具体分析内容包括: + * 它负责处理类似 {@code int x = 10;} 的声明语句,具体分析内容包括: *

                          *
                        • 类型解析: 将声明中的类型字符串转换为语义层的 {@link Type} 对象;
                        • *
                        • 符号定义: 将变量注册到当前作用域的 {@link SymbolTable} 中;
                        • diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java index 92197055..5ef4be4f 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java @@ -13,7 +13,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; /** * {@code LoopAnalyzer} 用于分析 for/while 等循环结构的语义正确性。 *

                          - * 主要职责如下: + * 主要职责如下: *

                            *
                          • 为整个循环体(包括初始化、条件、更新、循环体本身)创建独立的块级符号表(作用域),保证循环内变量与外部隔离。
                          • *
                          • 依次分析初始化语句、条件表达式、更新语句和循环体各语句,并递归检查嵌套的语法结构。
                          • diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/ReturnAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/ReturnAnalyzer.java index 35f2fcf9..25383dc1 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/ReturnAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/ReturnAnalyzer.java @@ -14,7 +14,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; /** * {@code ReturnAnalyzer} 是用于分析 {@link ReturnNode} 返回语句的语义分析器。 *

                            - * 它负责检查函数中的 return 语句是否与函数定义的返回类型匹配。分析流程包括: + * 它负责检查函数中的 return 语句是否与函数定义的返回类型匹配。分析流程包括: *

                              *
                            • 获取当前函数的返回类型 {@link FunctionType#returnType()};
                            • *
                            • 若 return 语句包含返回值表达式,检查其类型与函数定义是否兼容;
                            • diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java index 9f266c97..65cc6a60 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java @@ -4,7 +4,10 @@ import org.jcnc.snow.compiler.semantic.type.BuiltinType; import org.jcnc.snow.compiler.semantic.type.FunctionType; import org.jcnc.snow.compiler.semantic.type.Type; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** * BuiltinTypeRegistry - 语言全部内置类型/模块/函数注册中心 @@ -27,16 +30,17 @@ public final class BuiltinTypeRegistry { *

                              */ public static final Map BUILTIN_TYPES; + static { Map t = new HashMap<>(); - t.put("byte", BuiltinType.BYTE); // 字节型 - t.put("short", BuiltinType.SHORT); // 短整型 - t.put("int", BuiltinType.INT); // 整型 - t.put("long", BuiltinType.LONG); // 长整型 - t.put("float", BuiltinType.FLOAT); // 单精度浮点 + t.put("byte", BuiltinType.BYTE); // 字节型 + t.put("short", BuiltinType.SHORT); // 短整型 + t.put("int", BuiltinType.INT); // 整型 + t.put("long", BuiltinType.LONG); // 长整型 + t.put("float", BuiltinType.FLOAT); // 单精度浮点 t.put("double", BuiltinType.DOUBLE); // 双精度浮点 t.put("string", BuiltinType.STRING); // 字符串 - t.put("void", BuiltinType.VOID); // 无返回 + t.put("void", BuiltinType.VOID); // 无返回 t.put("boolean", BuiltinType.BOOLEAN); // 布尔类型 BUILTIN_TYPES = Collections.unmodifiableMap(t); // 不可变映射,防止被意外更改 @@ -45,7 +49,8 @@ public final class BuiltinTypeRegistry { /** * 私有构造方法,禁止实例化 */ - private BuiltinTypeRegistry() { } + private BuiltinTypeRegistry() { + } /** * 初始化内置模块和函数声明 diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzer.java index 8bdc377e..e1e181ce 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzer.java @@ -4,7 +4,9 @@ import org.jcnc.snow.compiler.parser.ast.ModuleNode; import org.jcnc.snow.compiler.semantic.analyzers.AnalyzerRegistry; import org.jcnc.snow.compiler.semantic.error.SemanticError; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; /** * {@code SemanticAnalyzer} 是编译器语义分析阶段的顶层调度器。 @@ -12,14 +14,14 @@ import java.util.*; * 它负责统一协调模块注册、函数签名登记和函数体语义检查等子任务,构建并维护语义上下文 {@link Context}, * 并最终输出所有收集到的语义错误列表 {@link SemanticError}。 *

                              - * 语义分析流程分为三个阶段: + * 语义分析流程分为三个阶段: *

                                *
                              1. 模块注册: 将所有用户模块的名称添加至全局模块表中,供后续导入检查与引用;
                              2. *
                              3. 函数签名注册: 提取函数定义的签名(名称与类型),填入每个模块对应的 {@link ModuleInfo};
                              4. *
                              5. 函数体检查: 遍历每个函数体,对所有语句与表达式执行类型检查和语义验证。
                              6. *
                              *

                              - * 内部使用组件: + * 内部使用组件: *

                                *
                              • {@link ModuleRegistry}: 注册用户模块;
                              • *
                              • {@link SignatureRegistrar}: 提取函数签名;
                              • @@ -30,10 +32,14 @@ import java.util.*; */ public class SemanticAnalyzer { - /** 全局语义分析上下文,包含模块信息、错误记录、分析器注册表等 */ + /** + * 全局语义分析上下文,包含模块信息、错误记录、分析器注册表等 + */ private final Context ctx; - /** 分析器注册表,管理语法节点与分析器之间的映射关系 */ + /** + * 分析器注册表,管理语法节点与分析器之间的映射关系 + */ private final AnalyzerRegistry registry = new AnalyzerRegistry(); // 分析流程中用到的核心子组件 diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzerRunner.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzerRunner.java index 11750549..7c835a93 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzerRunner.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/SemanticAnalyzerRunner.java @@ -11,14 +11,14 @@ import java.util.stream.Collectors; /** * {@code SemanticAnalyzerRunner} 是语义分析阶段的统一入口与调度器。 *

                                - * 功能职责: + * 功能职责: *

                                  *
                                • 从原始 AST 列表中过滤并收集所有 {@link ModuleNode} 节点,作为模块分析的起点;
                                • *
                                • 调用 {@link SemanticAnalyzer} 对所有模块节点执行完整语义分析流程;
                                • *
                                • 汇总并报告所有 {@link SemanticError};如有语义错误,自动中止编译流程,防止后续崩溃。
                                • *
                                *

                                - * 推荐使用方式: + * 推荐使用方式: *

                                  *     SemanticAnalyzerRunner.runSemanticAnalysis(ast, true);
                                  * 
                                diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/doc/README.md b/src/main/java/org/jcnc/snow/compiler/semantic/doc/README.md index baabb819..5dcc5a77 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/doc/README.md +++ b/src/main/java/org/jcnc/snow/compiler/semantic/doc/README.md @@ -5,9 +5,11 @@ ## 项目简介 **语义分析(Semantic Analysis)** 是 Snow 编译器在语法之后、IR 之前的关键阶段。 -该模块在遍历 AST 的同时,完成**类型推断与检查**、**符号与作用域解析**、**模块/结构体/函数签名登记**、以及**错误汇总与报告**,为后续 IR 生成与优化提供可靠、结构化的类型与符号信息。 +该模块在遍历 AST 的同时,完成**类型推断与检查**、**符号与作用域解析**、**模块/结构体/函数签名登记**、以及**错误汇总与报告** +,为后续 IR 生成与优化提供可靠、结构化的类型与符号信息。 -语义层采用“**注册表 + 访问器接口 + 分析器实现**”的可插拔设计:以 `AnalyzerRegistry` 为分发中心、`ExpressionAnalyzer`/`StatementAnalyzer` 为契约、配套 **模块/函数签名三阶段流程** 与 **类型系统**,形成清晰、易扩展、便于调试的语义分析框架。 +语义层采用“**注册表 + 访问器接口 + 分析器实现**”的可插拔设计:以 `AnalyzerRegistry` 为分发中心、`ExpressionAnalyzer`/ +`StatementAnalyzer` 为契约、配套 **模块/函数签名三阶段流程** 与 **类型系统**,形成清晰、易扩展、便于调试的语义分析框架。 ## 核心功能 @@ -49,7 +51,8 @@ * **类型系统与类型提升** * 核心接口:`Type`(`isCompatible`/`isNumeric`/`name`/`widen`) - * 具体类型:`BuiltinType`(byte/short/int/long/float/double/string/boolean/void)、`ArrayType`、`FunctionType`、`StructType` + * 具体类型:`BuiltinType`(byte/short/int/long/float/double/string/boolean/void)、`ArrayType`、`FunctionType`、 + `StructType` * 内建注册:`BuiltinTypeRegistry`(注册所有内置基本类型;示例内置模块 `os` 及函数 `syscall(string,int):void`) * 类型解析:`Context#parseType` 支持 **多维数组**(如 `int[][]`)、**结构体类型**(`模块.结构体`) * 数值宽化:在声明/赋值/调用/构造场景支持 **数值类型自动宽化**(`Type.widen`) @@ -144,7 +147,8 @@ semantic/ * **阶段化**:将“全局签名收集”和“函数体检查”解耦,避免前向引用/跨模块依赖导致的顺序问题。 * **作用域安全**:`SymbolTable` 通过父指针实现块级/函数级/模块级多层作用域;`If`/`Loop` 分支各自使用独立作用域。 * **解析顺序**:成员与调用遵循“先模块、后结构体、再本地符号”的解析策略,结合 `imports` 做跨模块访问控制。 -* **类型宽化**:对数值类型在声明/赋值/调用/构造时按 `Type.widen` 进行安全宽化;字符串调用形参支持从数值到 string 的隐式接收(见 `CallExpressionAnalyzer`)。 +* **类型宽化**:对数值类型在声明/赋值/调用/构造时按 `Type.widen` 进行安全宽化;字符串调用形参支持从数值到 string 的隐式接收(见 + `CallExpressionAnalyzer`)。 ## 扩展 diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/error/SemanticError.java b/src/main/java/org/jcnc/snow/compiler/semantic/error/SemanticError.java index c43e6c94..7c185da4 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/error/SemanticError.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/error/SemanticError.java @@ -26,7 +26,7 @@ import org.jcnc.snow.compiler.parser.ast.base.Node; public record SemanticError(Node node, String message) { /** - * 返回该语义错误的字符串描述,格式如下: + * 返回该语义错误的字符串描述,格式如下: *
                                      * [文件绝对路径: ]行 X, 列 Y: [错误信息]
                                      * 
                                diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/symbol/Symbol.java b/src/main/java/org/jcnc/snow/compiler/semantic/symbol/Symbol.java index 45fa4828..fa79f2db 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/symbol/Symbol.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/symbol/Symbol.java @@ -6,7 +6,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; * {@code Symbol} 表示符号表中的一条符号记录,描述语言中命名实体的语义信息。 *

                                * 符号是语义分析中的基础单元,通常用于表示变量、函数、参数等具名元素。 - * 每个符号具备以下三个核心属性: + * 每个符号具备以下三个核心属性: *

                                  *
                                • name: 符号的名称,例如变量名或函数名;
                                • *
                                • type: 符号的类型信息,通常为 {@link Type} 的子类实例;
                                • @@ -21,4 +21,5 @@ import org.jcnc.snow.compiler.semantic.type.Type; * @param type 符号所代表的类型,可为基础类型、函数类型等 * @param kind 符号种类,决定其语义用途(例如变量、函数、参数等) */ -public record Symbol(String name, Type type, SymbolKind kind) { } +public record Symbol(String name, Type type, SymbolKind kind) { +} diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/symbol/SymbolTable.java b/src/main/java/org/jcnc/snow/compiler/semantic/symbol/SymbolTable.java index 1438bf62..affc41ac 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/symbol/SymbolTable.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/symbol/SymbolTable.java @@ -9,7 +9,7 @@ import java.util.Map; * 本类支持嵌套作用域结构(Nested Scope),适用于块级作用域、函数作用域、模块作用域等语义环境建模。 * 每个符号表可挂接一个“父作用域”,以支持多层级作用域链上的符号解析。 * - *

                                  核心特性包括: + *

                                  核心特性包括: *

                                    *
                                  • 符号定义(局部作用域内唯一);
                                  • *
                                  • 符号查找(向上查找父作用域);
                                  • @@ -19,10 +19,14 @@ import java.util.Map; */ public class SymbolTable { - /** 父作用域引用,若为 {@code null} 则表示为最外层作用域(全局或根作用域) */ + /** + * 父作用域引用,若为 {@code null} 则表示为最外层作用域(全局或根作用域) + */ private final SymbolTable parent; - /** 当前作用域内定义的符号映射表(符号名 → {@link Symbol}) */ + /** + * 当前作用域内定义的符号映射表(符号名 → {@link Symbol}) + */ private final Map symbols = new HashMap<>(); /** @@ -53,7 +57,7 @@ public class SymbolTable { /** * 根据名称解析符号,支持作用域链向上递归查找。 - *

                                    查找策略: + *

                                    查找策略: *

                                      *
                                    1. 优先在当前作用域中查找该符号名称;
                                    2. *
                                    3. 若未找到且存在父作用域,则递归向上查找;
                                    4. diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java index 48170f5e..a12467e3 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java @@ -6,7 +6,7 @@ package org.jcnc.snow.compiler.semantic.type; * 类型涵盖整数、浮点、字符串及 void 类型,广泛应用于变量声明、 * 表达式类型推导、函数签名、类型检查等语义分析环节。 * - *

                                      支持的类型包括: + *

                                      支持的类型包括: *

                                        *
                                      • {@link #BYTE} - 8 位整数
                                      • *
                                      • {@link #SHORT} - 16 位整数
                                      • @@ -19,7 +19,7 @@ package org.jcnc.snow.compiler.semantic.type; *
                                      • {@link #VOID} - 空类型,用于表示无返回值的函数
                                      • *
                                      * - *

                                      每个枚举实例实现了 {@link Type} 接口,提供以下语义特性: + *

                                      每个枚举实例实现了 {@link Type} 接口,提供以下语义特性: *

                                        *
                                      • 数值类型判断 {@link #isNumeric()};
                                      • *
                                      • 类型兼容性判断 {@link #isCompatible(Type)};
                                      • @@ -41,7 +41,7 @@ public enum BuiltinType implements Type { /** * 判断当前类型是否与指定类型兼容。 *

                                        - * 兼容判断规则: + * 兼容判断规则: *

                                          *
                                        • 类型完全相同,视为兼容;
                                        • *
                                        • 对于数值类型,若目标类型为宽类型(如 int → double),视为兼容;
                                        • @@ -64,7 +64,7 @@ public enum BuiltinType implements Type { /** * 判断当前类型是否为数值类型。 *

                                          - * 数值类型包括: + * 数值类型包括: * {@link #BYTE}、{@link #SHORT}、{@link #INT}、{@link #LONG}、 * {@link #FLOAT}、{@link #DOUBLE}。 * diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/FunctionType.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/FunctionType.java index e3c38800..05eb3931 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/type/FunctionType.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/FunctionType.java @@ -8,12 +8,12 @@ import java.util.Objects; *

                                          * 适用于函数声明、函数调用、类型检查等语义分析场景。 *

                                          - * 例如,一个函数接受两个 {@code int} 参数并返回 {@code string},其函数类型为: + * 例如,一个函数接受两个 {@code int} 参数并返回 {@code string},其函数类型为: *

                                            *   (int, int) -> string
                                            * 
                                          * - *

                                          该类使用 Java 16+ {@code record} 语法定义,自动提供: + *

                                          该类使用 Java 16+ {@code record} 语法定义,自动提供: *

                                            *
                                          • 构造方法;
                                          • *
                                          • 访问器 {@code paramTypes()} 和 {@code returnType()};
                                          • @@ -43,7 +43,7 @@ public record FunctionType(List paramTypes, Type returnType) implements Ty /** * 判断当前函数类型是否与另一个类型兼容。 *

                                            - * 兼容条件: + * 兼容条件: *

                                              *
                                            • 对方也是 {@code FunctionType};
                                            • *
                                            • 返回类型兼容(可宽化或完全匹配);
                                            • @@ -62,7 +62,7 @@ public record FunctionType(List paramTypes, Type returnType) implements Ty /** * 返回函数类型的标准字符串表示形式。 *

                                              - * 格式为: + * 格式为: *

                                                    *   (param1, param2, ...) -> returnType
                                                    * 
                                              @@ -78,7 +78,7 @@ public record FunctionType(List paramTypes, Type returnType) implements Ty /** * 判断两个函数类型是否相等。 *

                                              - * 相等条件为: + * 相等条件为: *

                                                *
                                              • 引用相同;
                                              • *
                                              • 或参数类型列表完全相等,且返回类型也相等。
                                              • diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java index 209e5786..14fb6c7a 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/Type.java @@ -5,25 +5,6 @@ package org.jcnc.snow.compiler.semantic.type; * 用于在语义分析中进行类型兼容性检查和统一表示。 */ public interface Type { - /** - * 判断当前类型是否与另一个类型兼容。 - * - * @param other 要检查兼容性的另一个类型 - * @return 如果兼容则返回 true,否则返回 false - */ - boolean isCompatible(Type other); - - /** - * 判断当前类型是否为数值类型(byte/short/int/long/float/double)。 - *

                                                - * 默认实现返回 false,BuiltinType 会覆盖此方法。 - * - * @return 如果是数值类型则返回 true,否则返回 false - */ - default boolean isNumeric() { - return false; - } - /** * 对两个数值类型执行宽化转换,返回“更宽”的那个类型。 *

                                                @@ -47,6 +28,30 @@ public interface Type { int ia = order.indexOf(a), ib = order.indexOf(b); return order.get(Math.max(ia, ib)); } - /** 类型名字符串(如 int、double[]) */ - default String name() { return toString(); } + + /** + * 判断当前类型是否与另一个类型兼容。 + * + * @param other 要检查兼容性的另一个类型 + * @return 如果兼容则返回 true,否则返回 false + */ + boolean isCompatible(Type other); + + /** + * 判断当前类型是否为数值类型(byte/short/int/long/float/double)。 + *

                                                + * 默认实现返回 false,BuiltinType 会覆盖此方法。 + * + * @return 如果是数值类型则返回 true,否则返回 false + */ + default boolean isNumeric() { + return false; + } + + /** + * 类型名字符串(如 int、double[]) + */ + default String name() { + return toString(); + } } diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/utils/SemanticAnalysisReporter.java b/src/main/java/org/jcnc/snow/compiler/semantic/utils/SemanticAnalysisReporter.java index eb332b81..477fc7df 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/utils/SemanticAnalysisReporter.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/utils/SemanticAnalysisReporter.java @@ -9,7 +9,7 @@ import static org.jcnc.snow.common.SnowConfig.print; /** * {@code SemanticAnalysisReporter} 用于在语义分析结束后汇总并打印所有收集到的 * {@link SemanticError}。为了同时满足“完整错误收集”与“按需快速失败”两种使用场景, - * 现在提供两个公共 API: + * 现在提供两个公共 API: *

                                                  *
                                                • {@link #report(List)} ‑ 仅打印,不终止;
                                                • *
                                                • {@link #reportAndExitIfNecessary(List)} ‑ 若存在错误则 打印并退出
                                                • @@ -18,7 +18,8 @@ import static org.jcnc.snow.common.SnowConfig.print; */ public final class SemanticAnalysisReporter { - private SemanticAnalysisReporter() { } + private SemanticAnalysisReporter() { + } /** * 打印语义分析结果;不会退出进程。 diff --git a/src/main/java/org/jcnc/snow/pkg/doc/README.md b/src/main/java/org/jcnc/snow/pkg/doc/README.md index d51a16bb..1feb7c40 100644 --- a/src/main/java/org/jcnc/snow/pkg/doc/README.md +++ b/src/main/java/org/jcnc/snow/pkg/doc/README.md @@ -4,7 +4,7 @@ ## 项目简介 -**包管理模块(pkg)** 是 Snow 构建工具的关键组成部分,承担“从配置到产物” 的整条流水线: +**包管理模块(pkg)** 是 Snow 构建工具的关键组成部分,承担“从配置到产物” 的整条流水线: 1. **DSL 解析**: 读取并解析 `.cloud` 配置文件,生成统一的项目/依赖/构建配置模型; 2. **生命周期编排**: 按 *INIT → RESOLVE\_DEPENDENCIES → COMPILE → PACKAGE → PUBLISH → CLEAN* 的顺序驱动构建流程; diff --git a/src/main/java/org/jcnc/snow/pkg/dsl/CloudDSLParser.java b/src/main/java/org/jcnc/snow/pkg/dsl/CloudDSLParser.java index 195b6ac4..fc5bbe0e 100644 --- a/src/main/java/org/jcnc/snow/pkg/dsl/CloudDSLParser.java +++ b/src/main/java/org/jcnc/snow/pkg/dsl/CloudDSLParser.java @@ -33,7 +33,9 @@ import java.util.regex.Pattern; */ public final class CloudDSLParser { - /** 匹配 sectionName { 的行 */ + /** + * 匹配 sectionName { 的行 + */ private static final Pattern SECTION_HEADER = Pattern.compile("^(\\w+)\\s*\\{\\s*$"); /** @@ -42,11 +44,16 @@ public final class CloudDSLParser { */ private static final Pattern KEY_VALUE = Pattern.compile("^(\\w+)\\s*=\\s*(.*?)\\s*(?:#.*)?$"); - /** 匹配仅为 } 的行 */ + /** + * 匹配仅为 } 的行 + */ private static final Pattern BLOCK_END = Pattern.compile("^}\\s*$"); - /** 工具类禁止实例化 */ - private CloudDSLParser() {} + /** + * 工具类禁止实例化 + */ + private CloudDSLParser() { + } /** * 解析指定 .cloud 文件为 {@link Project} 对象。 @@ -130,7 +137,7 @@ public final class CloudDSLParser { private static String unquote(String s) { if (s == null || s.length() < 2) return s; char first = s.charAt(0); - char last = s.charAt(s.length() - 1); + char last = s.charAt(s.length() - 1); if ((first == '"' && last == '"') || (first == '\'' && last == '\'')) { return s.substring(1, s.length() - 1); } diff --git a/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecycleManager.java b/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecycleManager.java index 69428716..d868a507 100644 --- a/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecycleManager.java +++ b/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecycleManager.java @@ -21,7 +21,9 @@ import java.util.Map; */ public final class LifecycleManager { - /** 生命周期阶段与对应任务的映射关系 */ + /** + * 生命周期阶段与对应任务的映射关系 + */ private final Map tasks = new EnumMap<>(LifecyclePhase.class); /** diff --git a/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecyclePhase.java b/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecyclePhase.java index 39d9759d..d1a204cd 100644 --- a/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecyclePhase.java +++ b/src/main/java/org/jcnc/snow/pkg/lifecycle/LifecyclePhase.java @@ -7,16 +7,28 @@ package org.jcnc.snow.pkg.lifecycle; *

                                                  */ public enum LifecyclePhase { - /** 初始化阶段 */ + /** + * 初始化阶段 + */ INIT, - /** 解析依赖阶段 */ + /** + * 解析依赖阶段 + */ RESOLVE_DEPENDENCIES, - /** 编译阶段 */ + /** + * 编译阶段 + */ COMPILE, - /** 打包阶段 */ + /** + * 打包阶段 + */ PACKAGE, - /** 发布阶段 */ + /** + * 发布阶段 + */ PUBLISH, - /** 清理阶段 */ + /** + * 清理阶段 + */ CLEAN } diff --git a/src/main/java/org/jcnc/snow/pkg/model/BuildConfiguration.java b/src/main/java/org/jcnc/snow/pkg/model/BuildConfiguration.java index de4b64c9..0ecd2daf 100644 --- a/src/main/java/org/jcnc/snow/pkg/model/BuildConfiguration.java +++ b/src/main/java/org/jcnc/snow/pkg/model/BuildConfiguration.java @@ -1,7 +1,7 @@ package org.jcnc.snow.pkg.model; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * 构建配置对象,封装构建过程中的所有选项。 @@ -11,7 +11,9 @@ import java.util.HashMap; */ public final class BuildConfiguration { - /** 存储所有配置项 */ + /** + * 存储所有配置项 + */ private final Map options; /** diff --git a/src/main/java/org/jcnc/snow/pkg/model/Dependency.java b/src/main/java/org/jcnc/snow/pkg/model/Dependency.java index 3b23a912..54dd9c3b 100644 --- a/src/main/java/org/jcnc/snow/pkg/model/Dependency.java +++ b/src/main/java/org/jcnc/snow/pkg/model/Dependency.java @@ -11,7 +11,7 @@ import java.util.regex.Pattern; *

                                                  * *
                                                  - * 示例用法: 
                                                  + * 示例用法:
                                                    * Dependency dep = Dependency.fromString(
                                                    *     "core", "com.example:core:@{version}",
                                                    *     Map.of("version", "1.2.3")
                                                  @@ -30,7 +30,9 @@ public record Dependency(
                                                           String version
                                                   ) {
                                                   
                                                  -    /** 匹配 group:artifact:version 格式的正则表达式。 */
                                                  +    /**
                                                  +     * 匹配 group:artifact:version 格式的正则表达式。
                                                  +     */
                                                       private static final Pattern GAV = Pattern.compile("([^:]+):([^:]+):(.+)");
                                                   
                                                       /**
                                                  diff --git a/src/main/java/org/jcnc/snow/pkg/model/Project.java b/src/main/java/org/jcnc/snow/pkg/model/Project.java
                                                  index a46aa19b..13254950 100644
                                                  --- a/src/main/java/org/jcnc/snow/pkg/model/Project.java
                                                  +++ b/src/main/java/org/jcnc/snow/pkg/model/Project.java
                                                  @@ -19,28 +19,50 @@ import java.util.Map;
                                                    */
                                                   public final class Project {
                                                   
                                                  -    /** 组织/分组名(如 com.example) */
                                                  +    /**
                                                  +     * 组织/分组名(如 com.example)
                                                  +     */
                                                       private final String group;
                                                  -    /** 构件/模块名(如 app-core) */
                                                  +    /**
                                                  +     * 构件/模块名(如 app-core)
                                                  +     */
                                                       private final String artifact;
                                                  -    /** 项目展示名称 */
                                                  +    /**
                                                  +     * 项目展示名称
                                                  +     */
                                                       private final String name;
                                                  -    /** 版本号(如 1.0.0) */
                                                  +    /**
                                                  +     * 版本号(如 1.0.0)
                                                  +     */
                                                       private final String version;
                                                  -    /** 项目描述 */
                                                  +    /**
                                                  +     * 项目描述
                                                  +     */
                                                       private final String description;
                                                  -    /** 许可证标识 */
                                                  +    /**
                                                  +     * 许可证标识
                                                  +     */
                                                       private final String license;
                                                  -    /** 项目主页 URL */
                                                  +    /**
                                                  +     * 项目主页 URL
                                                  +     */
                                                       private final String homepage;
                                                   
                                                  -    /** 额外属性(不影响主字段,可用于模板/占位符) */
                                                  +    /**
                                                  +     * 额外属性(不影响主字段,可用于模板/占位符)
                                                  +     */
                                                       private final Map properties;
                                                  -    /** 仓库列表(仓库 ID -> 仓库对象) */
                                                  +    /**
                                                  +     * 仓库列表(仓库 ID -> 仓库对象)
                                                  +     */
                                                       private final Map repositories;
                                                  -    /** 依赖列表 */
                                                  +    /**
                                                  +     * 依赖列表
                                                  +     */
                                                       private final List dependencies;
                                                  -    /** 构建配置 */
                                                  +    /**
                                                  +     * 构建配置
                                                  +     */
                                                       private final BuildConfiguration build;
                                                   
                                                       /**
                                                  @@ -73,7 +95,7 @@ public final class Project {
                                                       }
                                                   
                                                       /**
                                                  -     * 通过扁平 Map 创建 Project 实例。key 格式约定如下: 
                                                  +     * 通过扁平 Map 创建 Project 实例。key 格式约定如下:
                                                        * 
                                                    *
                                                  • project.* —— 项目元数据
                                                  • *
                                                  • properties.* —— 额外属性
                                                  • @@ -133,57 +155,79 @@ public final class Project { return new Project(group, artifact, name, version, description, license, homepage, props, repos, deps, buildCfg); } - /** @return 组织/分组名 */ + /** + * @return 组织/分组名 + */ public String getGroup() { return group; } - /** @return 构件/模块名 */ + /** + * @return 构件/模块名 + */ public String getArtifact() { return artifact; } - /** @return 项目名称 */ + /** + * @return 项目名称 + */ public String getName() { return name; } - /** @return 版本号 */ + /** + * @return 版本号 + */ public String getVersion() { return version; } - /** @return 项目描述 */ + /** + * @return 项目描述 + */ public String getDescription() { return description; } - /** @return 许可证标识 */ + /** + * @return 许可证标识 + */ public String getLicense() { return license; } - /** @return 项目主页 URL */ + /** + * @return 项目主页 URL + */ public String getHomepage() { return homepage; } - /** @return 额外属性映射 */ + /** + * @return 额外属性映射 + */ public Map getProperties() { return properties; } - /** @return 仓库映射 */ + /** + * @return 仓库映射 + */ public Map getRepositories() { return repositories; } - /** @return 依赖列表 */ + /** + * @return 依赖列表 + */ public List getDependencies() { return dependencies; } - /** @return 构建配置 */ + /** + * @return 构建配置 + */ public BuildConfiguration getBuild() { return build; } diff --git a/src/main/java/org/jcnc/snow/pkg/resolver/DependencyResolver.java b/src/main/java/org/jcnc/snow/pkg/resolver/DependencyResolver.java index 7c9dcf83..d0e0f47d 100644 --- a/src/main/java/org/jcnc/snow/pkg/resolver/DependencyResolver.java +++ b/src/main/java/org/jcnc/snow/pkg/resolver/DependencyResolver.java @@ -22,7 +22,9 @@ import java.util.Optional; */ public final class DependencyResolver { - /** 本地缓存目录 */ + /** + * 本地缓存目录 + */ private final Path localCache; /** diff --git a/src/main/java/org/jcnc/snow/pkg/tasks/CleanTask.java b/src/main/java/org/jcnc/snow/pkg/tasks/CleanTask.java index c21b1ade..5bc22a4e 100644 --- a/src/main/java/org/jcnc/snow/pkg/tasks/CleanTask.java +++ b/src/main/java/org/jcnc/snow/pkg/tasks/CleanTask.java @@ -46,7 +46,7 @@ public final class CleanTask implements Task { * 内部使用 try-with-resources 保证文件流自动关闭,避免资源泄漏。 *

                                                    * - * @param dir 需要删除的目录路径 + * @param dir 需要删除的目录路径 * @param containSelf 是否删除指定目录本身 * @throws IOException 删除目录或文件过程中发生 IO 错误时抛出 */ diff --git a/src/main/java/org/jcnc/snow/pkg/tasks/PackageTask.java b/src/main/java/org/jcnc/snow/pkg/tasks/PackageTask.java index a04dcf0e..bfe50ecc 100644 --- a/src/main/java/org/jcnc/snow/pkg/tasks/PackageTask.java +++ b/src/main/java/org/jcnc/snow/pkg/tasks/PackageTask.java @@ -20,7 +20,9 @@ import java.util.zip.ZipOutputStream; */ public final class PackageTask implements Task { - /** 目标项目元数据 */ + /** + * 目标项目元数据 + */ private final Project project; /** diff --git a/src/main/java/org/jcnc/snow/pkg/tasks/PublishTask.java b/src/main/java/org/jcnc/snow/pkg/tasks/PublishTask.java index 310b8fa4..58c857a9 100644 --- a/src/main/java/org/jcnc/snow/pkg/tasks/PublishTask.java +++ b/src/main/java/org/jcnc/snow/pkg/tasks/PublishTask.java @@ -11,7 +11,9 @@ import org.jcnc.snow.pkg.model.Project; */ public final class PublishTask implements Task { - /** 目标项目元数据 */ + /** + * 目标项目元数据 + */ private final Project project; /** diff --git a/src/main/java/org/jcnc/snow/vm/VMInitializer.java b/src/main/java/org/jcnc/snow/vm/VMInitializer.java index ca11e3bf..835db8d9 100644 --- a/src/main/java/org/jcnc/snow/vm/VMInitializer.java +++ b/src/main/java/org/jcnc/snow/vm/VMInitializer.java @@ -1,9 +1,9 @@ package org.jcnc.snow.vm; import org.jcnc.snow.common.Mode; -import org.jcnc.snow.vm.execution.CommandLoader; import org.jcnc.snow.vm.engine.VMCommandExecutor; import org.jcnc.snow.vm.engine.VirtualMachineEngine; +import org.jcnc.snow.vm.execution.CommandLoader; import org.jcnc.snow.vm.io.FilePathResolver; import org.jcnc.snow.vm.utils.VMStateLogger; diff --git a/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java b/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java index c46571cb..c5839629 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java @@ -1,6 +1,5 @@ package org.jcnc.snow.vm.commands.flow.control; -import org.jcnc.snow.common.Mode; import org.jcnc.snow.vm.interfaces.Command; import org.jcnc.snow.vm.module.*; @@ -61,7 +60,7 @@ public class CallCommand implements Command { /* ----------- Parse target address / method signature ----------- */ final String targetToken = parts[1]; // Can be a numeric address or "@Class::method" - final int nArgs = Integer.parseInt(parts[2]); + final int nArgs = Integer.parseInt(parts[2]); /* ----------- Build callee's local variable store ----------- */ LocalVariableStore calleeLVS = new LocalVariableStore(); diff --git a/src/main/java/org/jcnc/snow/vm/commands/flow/control/JumpCommand.java b/src/main/java/org/jcnc/snow/vm/commands/flow/control/JumpCommand.java index 7f538908..b570ae41 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/flow/control/JumpCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/flow/control/JumpCommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.flow.control; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The JumpCommand class implements the {@link Command} interface and represents an unconditional jump instruction in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java index d7e314d7..85693ac4 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RLoadCommand.java @@ -33,10 +33,10 @@ public final class RLoadCommand implements Command { * Executes the {@code R_LOAD} instruction, loading a reference from the local variable table and pushing it onto the operand stack. * * @param parts The instruction parameters. {@code parts[0]} is the operator ("R_LOAD"), {@code parts[1]} is the slot index. - * @param pc The current program counter value, indicating the instruction address being executed. + * @param pc The current program counter value, indicating the instruction address being executed. * @param stack The operand stack manager. The loaded reference will be pushed onto this stack. - * @param lvs The local variable store. (Not used directly, as this command uses the store from the current stack frame.) - * @param cs The call stack manager. The reference will be loaded from the local variable store of the top stack frame. + * @param lvs The local variable store. (Not used directly, as this command uses the store from the current stack frame.) + * @param cs The call stack manager. The reference will be loaded from the local variable store of the top stack frame. * @return The next program counter value ({@code pc + 1}), pointing to the next instruction. * @throws NumberFormatException if the slot parameter cannot be parsed as an integer. */ diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java index 228f957d..741fc928 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RPushCommand.java @@ -38,107 +38,9 @@ import java.util.List; */ public class RPushCommand implements Command { - /** - * Executes the {@code R_PUSH} instruction. Parses the given literal parameter and pushes it onto the operand stack. - *

                                                    - * Handles: - *

                                                      - *
                                                    • Array literals (e.g., {@code [1, 2, "a"]}), parsed recursively as mutable ArrayLists
                                                    • - *
                                                    • Quoted string literals (e.g., {@code "abc\n"}), parsed with escape sequence support
                                                    • - *
                                                    • Unquoted raw strings, numbers, and atoms
                                                    • - *
                                                    - * - * @param parts The instruction split into parts (opcode and arguments) - * @param pc The current program counter - * @param stack The operand stack to push the value onto - * @param local The local variable store (unused) - * @param callStack The call stack (unused) - * @return The next program counter (pc + 1) - * @throws IllegalStateException if the R_PUSH parameter is missing or parsing fails - */ - @Override - public int execute(String[] parts, int pc, OperandStack stack, LocalVariableStore local, CallStack callStack) { - if (parts.length < 2) - throw new IllegalStateException("R_PUSH missing parameter"); - - // Join all arguments into a complete literal string - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < parts.length; i++) { - if (i > 1) sb.append(' '); - sb.append(parts[i]); - } - String literal = sb.toString().trim(); - - // Handle array literal - if (literal.startsWith("[") && literal.endsWith("]")) { - Object parsed = parseValue(new Cursor(literal)); - if (!(parsed instanceof List list)) { - stack.push(parsed); - } else { - stack.push(deepMutable(list)); - } - } - // String literal with quotes and escapes - else if (literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"")) { - String decoded = parseQuoted(new Cursor(literal)); - stack.push(decoded); - } - // Raw atom or string - else { - stack.push(literal); - } - return pc + 1; - } - - /** - * Utility class for string parsing, used by the array and string literal parsers. - */ - static class Cursor { - final String s; - int i; - - /** - * Constructs a cursor over the provided string. - * @param s the input string to parse - */ - Cursor(String s) { this.s = s; this.i = 0; } - - /** - * Advances the cursor by one character. - */ - void skip() { i++; } - - /** - * Returns true if the cursor has reached the end of the string. - * @return true if end of string - */ - boolean end() { return i >= s.length(); } - - /** - * Returns the current character at the cursor position. - * @return the current character - */ - char ch() { return s.charAt(i); } - } - - /** - * Parses a value from the current cursor position. - * Supports arrays, quoted strings, or atoms. - * - * @param c the parsing cursor - * @return the parsed object (List, String, Number, Boolean, or String fallback) - */ - Object parseValue(Cursor c) { - skipWs(c); - if (c.end()) return ""; - char ch = c.ch(); - if (ch == '[') return parseArray(c); - if (ch == '\"') return parseQuoted(c); - return parseAtom(c); - } - /** * Skips whitespace characters at the cursor. + * * @param c the parsing cursor */ private static void skipWs(Cursor c) { @@ -149,33 +51,6 @@ public class RPushCommand implements Command { } } - /** - * Parses an array literal of the form [elem1, elem2, ...] (may be nested). - * Recursively parses elements using {@link #parseValue(Cursor)}. - * - * @param c the parsing cursor - * @return a List of parsed elements - */ - private Object parseArray(Cursor c) { - c.skip(); // skip '[' - List out = new ArrayList<>(); - skipWs(c); - while (!c.end()) { - if (c.ch() == ']') { - c.skip(); // skip ']' - break; - } - Object v = parseValue(c); - out.add(v); - skipWs(c); - if (!c.end() && c.ch() == ',') { - c.skip(); - skipWs(c); - } - } - return out; - } - /** * Parses a quoted string, handling standard Java escape sequences (e.g. \n, \t, uXXXX). * @@ -273,6 +148,126 @@ public class RPushCommand implements Command { } } + /** + * Creates a deeply mutable version of the provided list (and its nested lists). + * + * @param l the original list + * @return a new mutable list (ArrayList), with all nested lists mutable + */ + private static java.util.List deepMutable(java.util.List l) { + java.util.List out = new java.util.ArrayList<>(l.size()); + for (Object v : l) out.add(deepMutableObject(v)); + return out; + } + + /** + * Helper for {@link #deepMutable(List)}; handles nested lists recursively. + * + * @param v the object to process + * @return a mutable list if input is a list; otherwise, the object itself + */ + private static Object deepMutableObject(Object v) { + if (v instanceof java.util.List l) { + return deepMutable(l); + } + return v; + } + + /** + * Executes the {@code R_PUSH} instruction. Parses the given literal parameter and pushes it onto the operand stack. + *

                                                    + * Handles: + *

                                                      + *
                                                    • Array literals (e.g., {@code [1, 2, "a"]}), parsed recursively as mutable ArrayLists
                                                    • + *
                                                    • Quoted string literals (e.g., {@code "abc\n"}), parsed with escape sequence support
                                                    • + *
                                                    • Unquoted raw strings, numbers, and atoms
                                                    • + *
                                                    + * + * @param parts The instruction split into parts (opcode and arguments) + * @param pc The current program counter + * @param stack The operand stack to push the value onto + * @param local The local variable store (unused) + * @param callStack The call stack (unused) + * @return The next program counter (pc + 1) + * @throws IllegalStateException if the R_PUSH parameter is missing or parsing fails + */ + @Override + public int execute(String[] parts, int pc, OperandStack stack, LocalVariableStore local, CallStack callStack) { + if (parts.length < 2) + throw new IllegalStateException("R_PUSH missing parameter"); + + // Join all arguments into a complete literal string + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < parts.length; i++) { + if (i > 1) sb.append(' '); + sb.append(parts[i]); + } + String literal = sb.toString().trim(); + + // Handle array literal + if (literal.startsWith("[") && literal.endsWith("]")) { + Object parsed = parseValue(new Cursor(literal)); + if (!(parsed instanceof List list)) { + stack.push(parsed); + } else { + stack.push(deepMutable(list)); + } + } + // String literal with quotes and escapes + else if (literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"")) { + String decoded = parseQuoted(new Cursor(literal)); + stack.push(decoded); + } + // Raw atom or string + else { + stack.push(literal); + } + return pc + 1; + } + + /** + * Parses a value from the current cursor position. + * Supports arrays, quoted strings, or atoms. + * + * @param c the parsing cursor + * @return the parsed object (List, String, Number, Boolean, or String fallback) + */ + Object parseValue(Cursor c) { + skipWs(c); + if (c.end()) return ""; + char ch = c.ch(); + if (ch == '[') return parseArray(c); + if (ch == '\"') return parseQuoted(c); + return parseAtom(c); + } + + /** + * Parses an array literal of the form [elem1, elem2, ...] (may be nested). + * Recursively parses elements using {@link #parseValue(Cursor)}. + * + * @param c the parsing cursor + * @return a List of parsed elements + */ + private Object parseArray(Cursor c) { + c.skip(); // skip '[' + List out = new ArrayList<>(); + skipWs(c); + while (!c.end()) { + if (c.ch() == ']') { + c.skip(); // skip ']' + break; + } + Object v = parseValue(c); + out.add(v); + skipWs(c); + if (!c.end() && c.ch() == ',') { + c.skip(); + skipWs(c); + } + } + return out; + } + /** * Creates a deeply unmodifiable version of the provided list (and its nested lists). * @@ -299,27 +294,45 @@ public class RPushCommand implements Command { } /** - * Creates a deeply mutable version of the provided list (and its nested lists). - * - * @param l the original list - * @return a new mutable list (ArrayList), with all nested lists mutable + * Utility class for string parsing, used by the array and string literal parsers. */ - private static java.util.List deepMutable(java.util.List l) { - java.util.List out = new java.util.ArrayList<>(l.size()); - for (Object v : l) out.add(deepMutableObject(v)); - return out; - } + static class Cursor { + final String s; + int i; - /** - * Helper for {@link #deepMutable(List)}; handles nested lists recursively. - * - * @param v the object to process - * @return a mutable list if input is a list; otherwise, the object itself - */ - private static Object deepMutableObject(Object v) { - if (v instanceof java.util.List l) { - return deepMutable(l); + /** + * Constructs a cursor over the provided string. + * + * @param s the input string to parse + */ + Cursor(String s) { + this.s = s; + this.i = 0; + } + + /** + * Advances the cursor by one character. + */ + void skip() { + i++; + } + + /** + * Returns true if the cursor has reached the end of the string. + * + * @return true if end of string + */ + boolean end() { + return i >= s.length(); + } + + /** + * Returns the current character at the cursor position. + * + * @return the current character + */ + char ch() { + return s.charAt(i); } - return v; } } diff --git a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java index 02379088..6c32e1a9 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/ref/control/RStoreCommand.java @@ -41,7 +41,7 @@ public final class RStoreCommand implements Command { * @param lvs The local variable store. (Not used directly, as the store from the current stack frame is used.) * @param cs The call stack manager. The reference will be stored in the local variable store of the top stack frame. * @return The next program counter value ({@code pc + 1}), pointing to the next instruction. - * @throws NumberFormatException if the slot parameter cannot be parsed as an integer. + * @throws NumberFormatException if the slot parameter cannot be parsed as an integer. * @throws java.util.EmptyStackException if the operand stack is empty when popping. */ @Override diff --git a/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java b/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java index 71e208c5..77841a51 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/system/control/HaltCommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.system.control; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The HaltCommand class implements the {@link Command} interface and represents the stop instruction in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAddCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAddCommand.java index 7da26448..65b9cb07 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAddCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAddCommand.java @@ -50,7 +50,7 @@ public class BAddCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the addition and push the result back onto the stack - operandStack.push((byte)(a + b)); + operandStack.push((byte) (a + b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAndCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAndCommand.java index 8eb94c96..22e97416 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAndCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BAndCommand.java @@ -49,7 +49,7 @@ public class BAndCommand implements Command { final byte a = (byte) operandStack.pop(); // Perform the byte8 bitwise AND operation and push the result back onto the stack - operandStack.push((byte)(a & b)); + operandStack.push((byte) (a & b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BDivCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BDivCommand.java index b71abb7d..99b8ca68 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BDivCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BDivCommand.java @@ -56,7 +56,7 @@ public class BDivCommand implements Command { } // Perform the division and push the result back onto the stack - operandStack.push((byte)(a / b)); + operandStack.push((byte) (a / b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BModCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BModCommand.java index 9a4747b2..d7c4a49c 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BModCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BModCommand.java @@ -50,7 +50,7 @@ public class BModCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the modulus operation and push the result back onto the stack - operandStack.push((byte)(a % b)); + operandStack.push((byte) (a % b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BMulCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BMulCommand.java index 8f0bc7da..06b124a1 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BMulCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BMulCommand.java @@ -50,7 +50,7 @@ public class BMulCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the multiplication and push the result back onto the stack - operandStack.push((byte)(a * b)); + operandStack.push((byte) (a * b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BOrCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BOrCommand.java index e29aaae8..3eec98c4 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BOrCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BOrCommand.java @@ -49,7 +49,7 @@ public class BOrCommand implements Command { final byte a = (byte) operandStack.pop(); // Perform the byte8 bitwise OR operation and push the result back onto the stack - operandStack.push((byte)(a | b)); + operandStack.push((byte) (a | b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BSubCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BSubCommand.java index 7f3f22e6..cceddff5 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BSubCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BSubCommand.java @@ -50,7 +50,7 @@ public class BSubCommand implements Command { byte a = (byte) operandStack.pop(); // Perform the subtraction and push the result back onto the stack - operandStack.push((byte)(a - b)); + operandStack.push((byte) (a - b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BXorCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BXorCommand.java index 478edb99..5f5e6ed3 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BXorCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/byte8/BXorCommand.java @@ -49,7 +49,7 @@ public class BXorCommand implements Command { final byte a = (byte) operandStack.pop(); // Perform the byte8 bitwise XOR operation and push the result back onto the stack - operandStack.push((byte)(a ^ b)); + operandStack.push((byte) (a ^ b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICECommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICECommand.java index cf35a542..a3461494 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICECommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICECommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGCommand.java index 12463a80..e4ef0846 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGCommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICGCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGECommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGECommand.java index a689a509..a8c07571 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGECommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICGECommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICGECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLCommand.java index 4a566317..2960e59d 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLCommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICLCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLECommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLECommand.java index 6de4e402..336d054c 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLECommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICLECommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICLECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine. diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICNECommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICNECommand.java index 114d75a8..02199c87 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICNECommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/int32/ICNECommand.java @@ -1,10 +1,10 @@ package org.jcnc.snow.vm.commands.type.control.int32; import org.jcnc.snow.vm.interfaces.Command; -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.module.CallStack; import org.jcnc.snow.vm.module.LocalVariableStore; import org.jcnc.snow.vm.module.OperandStack; +import org.jcnc.snow.vm.utils.LoggingUtils; /** * The ICNECommand class implements the {@link Command} interface and represents a conditional jump command diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAddCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAddCommand.java index 23226394..f312e9e6 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAddCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAddCommand.java @@ -50,7 +50,7 @@ public class SAddCommand implements Command { short a = (short) operandStack.pop(); // Perform the addition and push the result back onto the stack - operandStack.push((short)(a + b)); + operandStack.push((short) (a + b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAndCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAndCommand.java index e2c3d896..52a27d93 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAndCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SAndCommand.java @@ -49,7 +49,7 @@ public class SAndCommand implements Command { final short a = (short) operandStack.pop(); // Perform the short16 bitwise AND operation and push the result back onto the stack - operandStack.push((short)(a & b)); + operandStack.push((short) (a & b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SDivCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SDivCommand.java index d8385a24..1f018532 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SDivCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SDivCommand.java @@ -56,7 +56,7 @@ public class SDivCommand implements Command { } // Perform the division and push the result back onto the stack - operandStack.push((short)(a / b)); + operandStack.push((short) (a / b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SModCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SModCommand.java index 1a78486f..e670449e 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SModCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SModCommand.java @@ -50,7 +50,7 @@ public class SModCommand implements Command { short a = (short) operandStack.pop(); // Perform the modulus operation and push the result back onto the stack - operandStack.push((short)(a % b)); + operandStack.push((short) (a % b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SMulCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SMulCommand.java index 49d34d70..02f14f95 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SMulCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SMulCommand.java @@ -50,7 +50,7 @@ public class SMulCommand implements Command { short a = (short) operandStack.pop(); // Perform the multiplication and push the result back onto the stack - operandStack.push((short)(a * b)); + operandStack.push((short) (a * b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SOrCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SOrCommand.java index 72a88444..15fa3393 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SOrCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SOrCommand.java @@ -49,7 +49,7 @@ public class SOrCommand implements Command { final short a = (short) operandStack.pop(); // Perform the short16 bitwise OR operation and push the result back onto the stack - operandStack.push((short)(a | b)); + operandStack.push((short) (a | b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SSubCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SSubCommand.java index d16d0e09..b3f70dc3 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SSubCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SSubCommand.java @@ -50,7 +50,7 @@ public class SSubCommand implements Command { short a = (short) operandStack.pop(); // Perform the subtraction and push the result back onto the stack - operandStack.push((short)(a - b)); + operandStack.push((short) (a - b)); // Return the updated program counter (next instruction) return currentPC + 1; diff --git a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SXorCommand.java b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SXorCommand.java index dd0a8bec..5e33375c 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SXorCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/type/control/short16/SXorCommand.java @@ -49,7 +49,7 @@ public class SXorCommand implements Command { final short a = (short) operandStack.pop(); // Perform the short16 bitwise XOR operation and push the result back onto the stack - operandStack.push((short)(a ^ b)); + operandStack.push((short) (a ^ b)); return currentPC + 1; } diff --git a/src/main/java/org/jcnc/snow/vm/doc/README.md b/src/main/java/org/jcnc/snow/vm/doc/README.md index e92f4f37..07f14a4f 100644 --- a/src/main/java/org/jcnc/snow/vm/doc/README.md +++ b/src/main/java/org/jcnc/snow/vm/doc/README.md @@ -5,15 +5,18 @@ ## 项目简介 本模块实现了 Snow 的**指令集虚拟机(VM)**,用于运行由编译器/汇编器生成的“文本化指令序列”。 -它采用**命令(Command)模式 + 统一操作码表(`VMOpCode`)+ 工厂注册(`CommandFactory`)**的结构,配合**运行时栈/局部变量表/调用栈**与**方法栈帧**,构成清晰可扩展的执行层。 +它采用**命令(Command)模式 + 统一操作码表(`VMOpCode`)+ 工厂注册(`CommandFactory`)**的结构,配合**运行时栈/局部变量表/调用栈 +**与**方法栈帧**,构成清晰可扩展的执行层。 -执行流程:`VMLauncher/VMInitializer` 解析指令文件 → `CommandLoader` 读入并清洗文本 → `VirtualMachineEngine` 主循环按 **PC** 逐条解释执行(跳过空行与 `#` 注释),通过 `CommandExecutionHandler` 分发到各具体指令类,直到 `RET`(根帧)或 `HALT` 正常终止。 +执行流程:`VMLauncher/VMInitializer` 解析指令文件 → `CommandLoader` 读入并清洗文本 → `VirtualMachineEngine` 主循环按 **PC +** 逐条解释执行(跳过空行与 `#` 注释),通过 `CommandExecutionHandler` 分发到各具体指令类,直到 `RET`(根帧)或 `HALT` 正常终止。 ## 核心功能 * **统一的指令与分发模型** * 抽象接口:`interfaces.Command#execute(String[] parts, int pc, OperandStack, LocalVariableStore, CallStack)` - * 操作码表:`engine.VMOpCode`(以 `int` 编码,分段保留:**0x0000–0x00DF 类型算术/比较/装载**、**0x00E0–0x00E2 引用操作**、**0x0100– 栈操作**、**0x0200– 流程控制**、**0x0300– 寄存器移动**、**0x0400– 系统**) + * 操作码表:`engine.VMOpCode`(以 `int` 编码,分段保留:**0x0000–0x00DF 类型算术/比较/装载**、**0x00E0–0x00E2 引用操作**、 + **0x0100– 栈操作**、**0x0200– 流程控制**、**0x0300– 寄存器移动**、**0x0400– 系统**) * 指令工厂:`factories.CommandFactory` 将 `opCode → Command` 静态注册,`CommandExecutionHandler#handle` 统一查表并调用 * **执行引擎与运行时** @@ -35,7 +38,8 @@ * **控制流与调用** * **无条件跳转**:`JumpCommand`(`JUMP`) - * **调用/返回**:`CallCommand`(`CALL`,从栈按**左到右**顺序取实参,建立新 `StackFrame` 并设置返回地址),`RetCommand`(`RET`,弹栈帧并回到调用点;根帧返回触发终止) + * **调用/返回**:`CallCommand`(`CALL`,从栈按**左到右**顺序取实参,建立新 `StackFrame` 并设置返回地址),`RetCommand`( + `RET`,弹栈帧并回到调用点;根帧返回触发终止) * **栈操作**:`PopCommand`(`POP`)、`DupCommand`(`DUP`)、`SwapCommand`(`SWAP`) * **寄存器移动**:`MovCommand`(`MOV src,dst`,在同一局部变量表内复制槽位) @@ -48,7 +52,8 @@ * **系统调用与 I/O** * 统一入口:`SyscallCommand`(`SYSCALL`),失败时约定**向栈压 `-1`** - * 文件/网络/控制台子命令(示例):`PRINT/PRINTLN`、`OPEN/CLOSE/READ/WRITE/SEEK`、`PIPE/DUP`、`SOCKET/CONNECT/BIND/LISTEN/ACCEPT`、`SELECT`,以及**数组访问** `ARR_GET/ARR_SET` + * 文件/网络/控制台子命令(示例):`PRINT/PRINTLN`、`OPEN/CLOSE/READ/WRITE/SEEK`、`PIPE/DUP`、 + `SOCKET/CONNECT/BIND/LISTEN/ACCEPT`、`SELECT`,以及**数组访问** `ARR_GET/ARR_SET` * 文件描述符表:`io.FDTable` 维护 **虚拟 fd → NIO Channel** 映射(内置 `0:stdin / 1:stdout / 2:stderr`) * 路径与装载:`io.FilePathResolver`、`io.FileIOUtils` 负责解析参数、读取文本并**去注释/去空行** 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 c333e34b..9f59179c 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VMOpCode.java @@ -1,8 +1,16 @@ package org.jcnc.snow.vm.engine; +import org.jcnc.snow.vm.commands.flow.control.CallCommand; +import org.jcnc.snow.vm.commands.flow.control.JumpCommand; +import org.jcnc.snow.vm.commands.flow.control.RetCommand; import org.jcnc.snow.vm.commands.ref.control.RLoadCommand; import org.jcnc.snow.vm.commands.ref.control.RPushCommand; import org.jcnc.snow.vm.commands.ref.control.RStoreCommand; +import org.jcnc.snow.vm.commands.register.control.MovCommand; +import org.jcnc.snow.vm.commands.stack.control.DupCommand; +import org.jcnc.snow.vm.commands.stack.control.PopCommand; +import org.jcnc.snow.vm.commands.stack.control.SwapCommand; +import org.jcnc.snow.vm.commands.system.control.HaltCommand; import org.jcnc.snow.vm.commands.system.control.SyscallCommand; import org.jcnc.snow.vm.commands.type.control.byte8.*; import org.jcnc.snow.vm.commands.type.control.double64.*; @@ -10,39 +18,7 @@ import org.jcnc.snow.vm.commands.type.control.float32.*; import org.jcnc.snow.vm.commands.type.control.int32.*; import org.jcnc.snow.vm.commands.type.control.long64.*; import org.jcnc.snow.vm.commands.type.control.short16.*; -import org.jcnc.snow.vm.commands.type.control.int32.IAndCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IOrCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IXorCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LAndCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LOrCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LXorCommand; -import org.jcnc.snow.vm.commands.flow.control.JumpCommand; -import org.jcnc.snow.vm.commands.flow.control.CallCommand; -import org.jcnc.snow.vm.commands.flow.control.RetCommand; -import org.jcnc.snow.vm.commands.register.control.MovCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BLoadCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BStoreCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DLoadCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DStoreCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FLoadCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FStoreCommand; -import org.jcnc.snow.vm.commands.type.control.int32.ILoadCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IStoreCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LLoadCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LStoreCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SLoadCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SStoreCommand; -import org.jcnc.snow.vm.commands.stack.control.DupCommand; -import org.jcnc.snow.vm.commands.stack.control.PopCommand; -import org.jcnc.snow.vm.commands.stack.control.SwapCommand; -import org.jcnc.snow.vm.commands.type.control.byte8.BPushCommand; -import org.jcnc.snow.vm.commands.type.control.double64.DPushCommand; -import org.jcnc.snow.vm.commands.type.control.float32.FPushCommand; -import org.jcnc.snow.vm.commands.type.control.int32.IPushCommand; -import org.jcnc.snow.vm.commands.type.control.long64.LPushCommand; -import org.jcnc.snow.vm.commands.type.control.short16.SPushCommand; import org.jcnc.snow.vm.commands.type.conversion.*; -import org.jcnc.snow.vm.commands.system.control.HaltCommand; import org.jcnc.snow.vm.module.LocalVariableStore; /** @@ -2487,71 +2463,71 @@ public class VMOpCode { // endregion Conversion // region Reference Control (0x00E0-0x00EF) - /** - * R_PUSH Opcode: Represents an operation that pushes an object reference (such as a String or any reference type) - * onto the operand stack. - *

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

                                                    - * - *

                                                    Execution Steps:

                                                    - *
                                                      - *
                                                    1. Parses the object reference literal (e.g., a string) from the instruction parameters.
                                                    2. - *
                                                    3. Creates or interprets the reference as an object instance if necessary.
                                                    4. - *
                                                    5. Pushes the reference object onto the operand stack.
                                                    6. - *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. - *
                                                    - * - *

                                                    This opcode is commonly used for:

                                                    - *
                                                      - *
                                                    • Pushing string literals, objects, or other references needed for subsequent operations.
                                                    • - *
                                                    • Supplying parameters for method calls that expect reference types.
                                                    • - *
                                                    • Initializing the operand stack with reference values for computation or storage.
                                                    • - *
                                                    - */ - public static final int R_PUSH = 0x00E0; - /** - * R_LOAD Opcode: Represents an operation that loads an object reference from the local variable table - * and pushes it onto the operand stack. - *

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

                                                    - * - *

                                                    Execution Steps:

                                                    - *
                                                      - *
                                                    1. Parses the target slot index from the instruction parameters.
                                                    2. - *
                                                    3. Retrieves the reference object stored at the specified slot in the local variable table - * of the current stack frame.
                                                    4. - *
                                                    5. Pushes the retrieved reference onto the operand stack.
                                                    6. - *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. - *
                                                    - * - *

                                                    This opcode is commonly used for:

                                                    - *
                                                      - *
                                                    • Accessing local variables (such as function arguments or local object references) during method execution.
                                                    • - *
                                                    • Preparing reference values for operations or method invocations.
                                                    • - *
                                                    • Reusing objects previously stored in local variables.
                                                    • - *
                                                    - */ - public static final int R_LOAD = 0x00E1; - /** - * R_STORE Opcode: Represents an operation that pops an object reference from the top of the operand stack - * and stores it into the local variable table at the specified slot index. - *

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

                                                    - * - *

                                                    Execution Steps:

                                                    - *
                                                      - *
                                                    1. Parses the target slot index from the instruction parameters.
                                                    2. - *
                                                    3. Pops the top reference object from the operand stack.
                                                    4. - *
                                                    5. Stores the popped reference object into the specified slot in the local variable table - * of the current stack frame.
                                                    6. - *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. - *
                                                    - * - *

                                                    This opcode is commonly used for:

                                                    - *
                                                      - *
                                                    • Storing computation results or intermediate reference values for later use.
                                                    • - *
                                                    • Passing object references to local variables in preparation for further operations or method calls.
                                                    • - *
                                                    • Managing object lifetimes and ensuring correct referencing in scoped execution contexts.
                                                    • - *
                                                    - */ - public static final int R_STORE = 0x00E2; + /** + * R_PUSH Opcode: Represents an operation that pushes an object reference (such as a String or any reference type) + * onto the operand stack. + *

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

                                                    + * + *

                                                    Execution Steps:

                                                    + *
                                                      + *
                                                    1. Parses the object reference literal (e.g., a string) from the instruction parameters.
                                                    2. + *
                                                    3. Creates or interprets the reference as an object instance if necessary.
                                                    4. + *
                                                    5. Pushes the reference object onto the operand stack.
                                                    6. + *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. + *
                                                    + * + *

                                                    This opcode is commonly used for:

                                                    + *
                                                      + *
                                                    • Pushing string literals, objects, or other references needed for subsequent operations.
                                                    • + *
                                                    • Supplying parameters for method calls that expect reference types.
                                                    • + *
                                                    • Initializing the operand stack with reference values for computation or storage.
                                                    • + *
                                                    + */ + public static final int R_PUSH = 0x00E0; + /** + * R_LOAD Opcode: Represents an operation that loads an object reference from the local variable table + * and pushes it onto the operand stack. + *

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

                                                    + * + *

                                                    Execution Steps:

                                                    + *
                                                      + *
                                                    1. Parses the target slot index from the instruction parameters.
                                                    2. + *
                                                    3. Retrieves the reference object stored at the specified slot in the local variable table + * of the current stack frame.
                                                    4. + *
                                                    5. Pushes the retrieved reference onto the operand stack.
                                                    6. + *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. + *
                                                    + * + *

                                                    This opcode is commonly used for:

                                                    + *
                                                      + *
                                                    • Accessing local variables (such as function arguments or local object references) during method execution.
                                                    • + *
                                                    • Preparing reference values for operations or method invocations.
                                                    • + *
                                                    • Reusing objects previously stored in local variables.
                                                    • + *
                                                    + */ + public static final int R_LOAD = 0x00E1; + /** + * R_STORE Opcode: Represents an operation that pops an object reference from the top of the operand stack + * and stores it into the local variable table at the specified slot index. + *

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

                                                    + * + *

                                                    Execution Steps:

                                                    + *
                                                      + *
                                                    1. Parses the target slot index from the instruction parameters.
                                                    2. + *
                                                    3. Pops the top reference object from the operand stack.
                                                    4. + *
                                                    5. Stores the popped reference object into the specified slot in the local variable table + * of the current stack frame.
                                                    6. + *
                                                    7. Increments the program counter (PC) to proceed with the next sequential instruction.
                                                    8. + *
                                                    + * + *

                                                    This opcode is commonly used for:

                                                    + *
                                                      + *
                                                    • Storing computation results or intermediate reference values for later use.
                                                    • + *
                                                    • Passing object references to local variables in preparation for further operations or method calls.
                                                    • + *
                                                    • Managing object lifetimes and ensuring correct referencing in scoped execution contexts.
                                                    • + *
                                                    + */ + public static final int R_STORE = 0x00E2; // endregion // region Stack Control (0x0100-0x01FF) diff --git a/src/main/java/org/jcnc/snow/vm/engine/VirtualMachineEngine.java b/src/main/java/org/jcnc/snow/vm/engine/VirtualMachineEngine.java index aa6d2279..b5554da0 100644 --- a/src/main/java/org/jcnc/snow/vm/engine/VirtualMachineEngine.java +++ b/src/main/java/org/jcnc/snow/vm/engine/VirtualMachineEngine.java @@ -19,7 +19,7 @@ import java.util.List; *
                                                  • {@link CallStack} — manages stack frames and return addresses
                                                  • *
                                                  • {@link CommandExecutionHandler} — dispatches opcodes
                                                  • * - * + *

                                                    * Root-frame contract: *

                                                    * A root stack frame is pushed once via @@ -31,10 +31,14 @@ public class VirtualMachineEngine { /* ---------- Constants ---------- */ - /** Sentinel PC value that signals “terminate program gracefully”. */ + /** + * Sentinel PC value that signals “terminate program gracefully”. + */ private static final int PROGRAM_END = Integer.MAX_VALUE; - /** Sentinel returned by {@link CommandExecutionHandler#handle} to halt immediately. */ + /** + * Sentinel returned by {@link CommandExecutionHandler#handle} to halt immediately. + */ private static final int HALT = -1; /* ---------- Runtime state ---------- */ @@ -52,8 +56,8 @@ public class VirtualMachineEngine { * Builds a VM engine with fresh runtime structures. */ public VirtualMachineEngine() { - this.operandStack = new OperandStack(); - this.callStack = new CallStack(); + this.operandStack = new OperandStack(); + this.callStack = new CallStack(); this.localVariableStore = new LocalVariableStore(); // shared with root frame this.commandExecutionHandler = new CommandExecutionHandler(operandStack, localVariableStore, callStack); @@ -61,7 +65,9 @@ public class VirtualMachineEngine { } /* package-private accessor used by debug helpers */ - CallStack getCallStack() { return callStack; } + CallStack getCallStack() { + return callStack; + } /* ---------- Execution ---------- */ @@ -144,19 +150,23 @@ public class VirtualMachineEngine { /* The returnAddress of the root frame must be PROGRAM_END so that the main loop can exit correctly when the root function RETs.*/ MethodContext rootCtx = new MethodContext("root", null); - StackFrame rootFrame = new StackFrame(PROGRAM_END, localVariableStore, rootCtx); + StackFrame rootFrame = new StackFrame(PROGRAM_END, localVariableStore, rootCtx); callStack.pushFrame(rootFrame); } /* ---------- Debug helpers ---------- */ - /** Prints operand stack + call-stack snapshot. */ + /** + * Prints operand stack + call-stack snapshot. + */ public void printStack() { operandStack.printOperandStack(); callStack.printCallStack(); } - /** Prints the local-variable table of the current top frame. */ + /** + * Prints the local-variable table of the current top frame. + */ public void printLocalVariables() { if (callStack.isEmpty()) { System.out.println("Local variable table is empty"); @@ -167,7 +177,9 @@ public class VirtualMachineEngine { /* ---------- Utility ---------- */ - /** Parses textual opcode to integer. */ + /** + * Parses textual opcode to integer. + */ private int parseOpCode(String opCodeStr) { try { return Integer.parseInt(opCodeStr); diff --git a/src/main/java/org/jcnc/snow/vm/execution/CommandLoader.java b/src/main/java/org/jcnc/snow/vm/execution/CommandLoader.java index 70d6c9b0..afe4a31e 100644 --- a/src/main/java/org/jcnc/snow/vm/execution/CommandLoader.java +++ b/src/main/java/org/jcnc/snow/vm/execution/CommandLoader.java @@ -1,9 +1,8 @@ package org.jcnc.snow.vm.execution; - -import org.jcnc.snow.vm.utils.LoggingUtils; import org.jcnc.snow.vm.io.FileIOUtils; +import org.jcnc.snow.vm.utils.LoggingUtils; import java.util.List; diff --git a/src/main/java/org/jcnc/snow/vm/io/FDTable.java b/src/main/java/org/jcnc/snow/vm/io/FDTable.java index 0cd40b0e..1293e4d9 100644 --- a/src/main/java/org/jcnc/snow/vm/io/FDTable.java +++ b/src/main/java/org/jcnc/snow/vm/io/FDTable.java @@ -3,7 +3,8 @@ package org.jcnc.snow.vm.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; -import java.nio.channels.*; +import java.nio.channels.Channel; +import java.nio.channels.Channels; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -19,11 +20,13 @@ import java.util.concurrent.atomic.AtomicInteger; */ public final class FDTable { - private FDTable() {} - - /** Next available fd (0‒2 are reserved for standard streams) */ + /** + * Next available fd (0‒2 are reserved for standard streams) + */ private static final AtomicInteger NEXT_FD = new AtomicInteger(3); - /** Main mapping table: fd → Channel */ + /** + * Main mapping table: fd → Channel + */ private static final ConcurrentHashMap MAP = new ConcurrentHashMap<>(); static { @@ -33,8 +36,12 @@ public final class FDTable { MAP.put(2, Channels.newChannel(new BufferedOutputStream(System.err))); } + private FDTable() { + } + /** * Register a new Channel, returning the allocated virtual fd. + * * @param ch Channel to register * @return allocated fd */ @@ -46,6 +53,7 @@ public final class FDTable { /** * Retrieve the Channel by fd; returns null if fd does not exist. + * * @param fd file descriptor * @return Channel or null if not found */ @@ -55,6 +63,7 @@ public final class FDTable { /** * Close and remove the fd (0‒2 are ignored). + * * @param fd file descriptor to close * @throws IOException if an I/O error occurs */ @@ -66,6 +75,7 @@ public final class FDTable { /** * Similar to dup(oldfd) — returns a new fd referring to the same Channel. + * * @param oldfd old file descriptor to duplicate * @return new fd referring to the same Channel * @throws IllegalArgumentException if fd does not exist diff --git a/src/main/java/org/jcnc/snow/vm/module/CallStack.java b/src/main/java/org/jcnc/snow/vm/module/CallStack.java index cd982d38..473a34bd 100644 --- a/src/main/java/org/jcnc/snow/vm/module/CallStack.java +++ b/src/main/java/org/jcnc/snow/vm/module/CallStack.java @@ -11,6 +11,7 @@ import java.util.Deque; public class CallStack { private static final int MAX_STACK_DEPTH = 1024; // Stack overflow protection private final Deque stack = new ArrayDeque<>(); + /** * Default constructor for creating an instance of CallStack. * This constructor is empty as no specific initialization is required. diff --git a/src/main/java/org/jcnc/snow/vm/module/Instance.java b/src/main/java/org/jcnc/snow/vm/module/Instance.java index 04c94513..87412e82 100644 --- a/src/main/java/org/jcnc/snow/vm/module/Instance.java +++ b/src/main/java/org/jcnc/snow/vm/module/Instance.java @@ -25,10 +25,14 @@ import java.util.Map; */ public final class Instance { - /** The virtual table associated with this instance (immutable). */ + /** + * The virtual table associated with this instance (immutable). + */ private final VirtualTable vtable; - /** A mapping of field names to their runtime values. */ + /** + * A mapping of field names to their runtime values. + */ private final Map fields = new HashMap<>(); /** diff --git a/src/main/java/org/jcnc/snow/vm/module/StackFrame.java b/src/main/java/org/jcnc/snow/vm/module/StackFrame.java index 39e708c8..4def3341 100644 --- a/src/main/java/org/jcnc/snow/vm/module/StackFrame.java +++ b/src/main/java/org/jcnc/snow/vm/module/StackFrame.java @@ -1,7 +1,5 @@ package org.jcnc.snow.vm.module; -import org.jcnc.snow.vm.utils.LoggingUtils; - /** * The {@code StackFrame} class represents a single frame in the call stack during program execution. * It holds the execution context for a method invocation, including information such as the return diff --git a/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java b/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java index f7e0fe6a..7ecda570 100644 --- a/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java +++ b/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java @@ -22,7 +22,9 @@ import java.util.Map; */ public final class VirtualTable { - /** Mapping from method signature to its entry address in the VM code segment. */ + /** + * Mapping from method signature to its entry address in the VM code segment. + */ private final Map table = new HashMap<>(); /** -- Gitee From d1d30968e93576affe21557b57b77d9b178a740d Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 09:29:48 +0800 Subject: [PATCH 06/19] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=A3=B0=E6=98=8E=E4=B8=AD=E7=9A=84=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handlers/DeclarationHandler.java | 106 +++++++++++++----- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java index 4b5e9db8..5367d05a 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java @@ -1,24 +1,68 @@ package org.jcnc.snow.compiler.ir.builder.statement.handlers; +import org.jcnc.snow.compiler.ir.builder.core.IRBuilderScope; import org.jcnc.snow.compiler.ir.builder.statement.IStatementHandler; import org.jcnc.snow.compiler.ir.builder.statement.StatementBuilderContext; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.DeclarationNode; +import org.jcnc.snow.compiler.parser.ast.NewExpressionNode; +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.StatementNode; /** - * 变量声明语句处理器。 + * 变量声明语句处理器(Declaration Statement Handler)。 *

                                                    - * 负责将AST中的DeclarationNode节点(如“int a = 1;”)编译为IR层的变量声明和初始化指令。 - * 支持带初始化器与不带初始化器两种情况,并自动管理常量传播和作用域绑定。 + * 负责将 AST 层的 {@link DeclarationNode}(如 {@code int a = 1;} 或 {@code Person p = new Student(...);}) + * 编译为中间表示(IR)的变量声明、初始化、类型绑定、作用域注册等。 + * 支持带初始化器和不带初始化器两种声明,并自动实现常量传播优化及多态类型推导。 *

                                                    + * 多态类型推导的核心实现: + *

                                                    + * 针对如 {@code declare x: Base = new Sub(...);} 这种父类变量直接赋 new 子类对象的情形, + * 若 {@code Sub} 确实继承自 {@code Base},则在当前作用域内注册变量时,将类型由 Base 升级为 Sub。 + * 这样后续所有基于该变量的成员方法调用(如 x.getName())都能静态绑定到子类重写实现(静态多态)。 + *

                                                    + * 处理流程: + *
                                                      + *
                                                    1. 如有初始化器,先记录变量声明类型并分配寄存器,生成初始化表达式指令。
                                                    2. + *
                                                    3. 尝试常量折叠,注册或清理常量绑定。
                                                    4. + *
                                                    5. 如初始化器为 new 子类(...),且子类继承自声明类型,则变量类型提升为子类。
                                                    6. + *
                                                    7. 最终在作用域注册变量名、类型(可能提升)、寄存器绑定。
                                                    8. + *
                                                    9. 如无初始化器,仅做类型和符号表注册,并清空常量绑定。
                                                    10. + *
                                                    + *

                                                    + * 注意事项: + *

                                                      + *
                                                    • 本实现不会影响已有运行时结构,适用于现有虚拟机/IR,不依赖对象 vtable 派发。
                                                    • + *
                                                    • 如需支持运行时真正多态,请在对象结构及方法调用指令层面额外设计。
                                                    • + *
                                                    */ public class DeclarationHandler implements IStatementHandler { + /** - * 判断是否可以处理给定的语句节点。 + * 判断类型 child 是否是 parent 的子类(包含多级继承)。 + * 依赖 IRBuilderScope 注册的 STRUCT_PARENTS。 * - * @param stmt AST语句节点 - * @return 若为DeclarationNode类型则返回true,否则返回false + * @param child 子类名 + * @param parent 父类名 + * @return 若 child 继承自 parent,返回 true,否则 false + */ + private static boolean isSubclassOf(String child, String parent) { + if (child == null || parent == null) return false; + if (child.equals(parent)) return true; + String t = child; + while (t != null) { + if (t.equals(parent)) return true; + t = IRBuilderScope.getStructParent(t); + } + return false; + } + + /** + * 判断当前 Handler 是否可处理给定 AST 语句节点。 + * + * @param stmt AST 语句节点 + * @return 若为 DeclarationNode 类型则返回 true,否则返回 false */ @Override public boolean canHandle(StatementNode stmt) { @@ -26,18 +70,9 @@ public class DeclarationHandler implements IStatementHandler { } /** - * 处理变量声明节点,生成变量声明与初始化的IR指令。 - *

                                                    - * 处理流程: - *

                                                      - *
                                                    1. 若有初始化器,先记录类型,生成目标寄存器,并对初始化表达式赋值。
                                                    2. - *
                                                    3. 尝试常量折叠,若为常量则注册为常量变量,否则清除常量绑定。
                                                    4. - *
                                                    5. 完成变量声明并注册到作用域。
                                                    6. - *
                                                    7. 无初始化器时只做类型和符号表注册,并清空常量绑定。
                                                    8. - *
                                                    - *

                                                    + * 处理变量声明语句(含类型提升及常量传播)。 * - * @param stmt AST语句节点(已保证为DeclarationNode类型) + * @param stmt AST 语句节点(已保证为 DeclarationNode 类型) * @param c 语句构建上下文 */ @Override @@ -45,24 +80,41 @@ public class DeclarationHandler implements IStatementHandler { DeclarationNode decl = (DeclarationNode) stmt; if (decl.getInitializer().isPresent()) { - // 1. 有初始化器:先临时设置类型,分配目标寄存器并生成赋值IR + ExpressionNode init = decl.getInitializer().get(); + + // 1. 临时记录变量声明类型,供初始化表达式类型推断 c.ctx().setVarType(decl.getType()); + + // 2. 分配目标寄存器,并生成初始化表达式代码 IRVirtualRegister dest = c.ctx().newRegister(); - c.expr().buildInto(decl.getInitializer().get(), dest); + c.expr().buildInto(init, dest); + // 3. 常量传播优化 try { - // 2. 尝试常量折叠,做常量传播优化 - Object constVal = c.constFolder().tryFoldConst(decl.getInitializer().get()); - if (constVal != null) c.ctx().getScope().setConstValue(decl.getName(), constVal); - else c.ctx().getScope().clearConstValue(decl.getName()); + Object constVal = c.constFolder().tryFoldConst(init); + if (constVal != null) { + c.ctx().getScope().setConstValue(decl.getName(), constVal); + } else { + c.ctx().getScope().clearConstValue(decl.getName()); + } } catch (Throwable ignored) { } - c.ctx().clearVarType(); - // 3. 注册变量到作用域,绑定寄存器 - c.ctx().getScope().declare(decl.getName(), decl.getType(), dest); + + // 4. 类型提升判定 + String effectiveType = decl.getType(); + if (init instanceof NewExpressionNode newExp) { + String newType = newExp.typeName(); + if (isSubclassOf(newType, effectiveType)) { + effectiveType = newType; + } + } + + // 5. 在作用域注册变量名、类型、寄存器 + c.ctx().getScope().declare(decl.getName(), effectiveType, dest); + } else { - // 4. 无初始化器,仅注册变量并清空常量绑定 + // 无初始化器:仅注册类型及符号,并清空常量绑定 c.ctx().getScope().declare(decl.getName(), decl.getType()); c.ctx().getScope().clearConstValue(decl.getName()); } -- Gitee From ce97a8fea38e7072aae5dd4655a48409ff5676c1 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 09:30:23 +0800 Subject: [PATCH 07/19] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E5=AD=97=E9=9D=A2=E9=87=8F=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jcnc/snow/compiler/ir/builder/handlers/NewHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/NewHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/NewHandler.java index 2e475012..e42a1b42 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/NewHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/NewHandler.java @@ -16,7 +16,9 @@ import java.util.List; /** * 数组字面量表达式处理器。 *

                                                    - * 负责将 [a, b, c] 数组字面量节点编译为 IR 常量表达式,转换流程包括: + * 负责将 [a, b, c] 数组字面量节点编译为 IR 常量表达式 + *

                                                    + * 转换流程: *

                                                      *
                                                    1. 递归遍历每个元素,确保全为编译期常量
                                                    2. *
                                                    3. 生成对应的 IRConstant 及 LoadConstInstruction 指令
                                                    4. -- Gitee From 010365e516ec590bbaef6cafbb92258a576d7bd2 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 09:56:24 +0800 Subject: [PATCH 08/19] =?UTF-8?q?docs:=20=E7=A7=BB=E9=99=A4=20DeclarationH?= =?UTF-8?q?andler=20=E7=B1=BB=E4=B8=AD=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ir/builder/statement/handlers/DeclarationHandler.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java index 5367d05a..086f7174 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/statement/handlers/DeclarationHandler.java @@ -31,11 +31,6 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode; *
                                                    5. 如无初始化器,仅做类型和符号表注册,并清空常量绑定。
                                                    6. *
                                                    *

                                                    - * 注意事项: - *

                                                      - *
                                                    • 本实现不会影响已有运行时结构,适用于现有虚拟机/IR,不依赖对象 vtable 派发。
                                                    • - *
                                                    • 如需支持运行时真正多态,请在对象结构及方法调用指令层面额外设计。
                                                    • - *
                                                    */ public class DeclarationHandler implements IStatementHandler { -- Gitee From eae45c5d2a589251fc76b05129f729787edaac92 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 11:54:27 +0800 Subject: [PATCH 09/19] =?UTF-8?q?refactor:=20=E7=AE=80=E5=8C=96CallCommand?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E5=AE=9E=E7=8E=B0=E5=92=8C=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 精简了`CallCommand`类的文档,使其更加简洁明了。 - 移除了对虚拟调用的支持,仅保留静态调用。 - 优化了参数验证和异常处理逻辑。 - 删除了未使用的`Instance`和`VirtualTable`类,因为它们不再被`CallCommand`使用。 - 更新了`LocalVariableStore`类的文档和内部实现,以提高可读性和性能。 --- .../vm/commands/flow/control/CallCommand.java | 101 +++++++--------- .../org/jcnc/snow/vm/module/Instance.java | 95 --------------- .../snow/vm/module/LocalVariableStore.java | 108 ++++++++++++------ .../org/jcnc/snow/vm/module/VirtualTable.java | 72 ------------ 4 files changed, 118 insertions(+), 258 deletions(-) delete mode 100644 src/main/java/org/jcnc/snow/vm/module/Instance.java delete mode 100644 src/main/java/org/jcnc/snow/vm/module/VirtualTable.java diff --git a/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java b/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java index c5839629..d8d43476 100644 --- a/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java +++ b/src/main/java/org/jcnc/snow/vm/commands/flow/control/CallCommand.java @@ -6,93 +6,78 @@ import org.jcnc.snow.vm.module.*; import static org.jcnc.snow.common.SnowConfig.print; /** - * The CallCommand class implements the {@link Command} interface and represents a subroutine/function call - * instruction in the virtual machine. - *

                                                    - * This command facilitates method invocation by creating a new stack frame, transferring arguments - * from the operand stack to the callee's local variable store, and jumping to the specified target address. - *

                                                    + * Implements the CALL instruction for the virtual machine. * - *

                                                    Specific behavior:

                                                    + *

                                                    + * Encoding (by {@code VMProgramBuilder.emitCall}): *

                                                      - *
                                                    • Parses the target address and the number of arguments from the instruction parameters.
                                                    • - *
                                                    • Validates the operands and checks for correct argument count.
                                                    • - *
                                                    • Builds a new local variable store for the callee and transfers arguments from the operand stack - * (left-to-right order, where the top of the stack is the last argument).
                                                    • - *
                                                    • Pushes a new stack frame onto the call stack, saving the return address and local variables.
                                                    • - *
                                                    • Jumps to the specified target address to begin execution of the callee function.
                                                    • - *
                                                    • If any error occurs (e.g., malformed operands, stack underflow), an exception is thrown.
                                                    • + *
                                                    • {@code CALL } — static/known target
                                                    • *
                                                    + * The arguments are pushed to the operand stack from left to right before the call, + * so the last argument is on the top of the stack when this instruction executes. + *

                                                    */ public class CallCommand implements Command { /** - * Executes the CALL instruction, initiating a subroutine/function call within the virtual machine. + * Executes the CALL instruction. + * *

                                                    - * This method handles the creation of a new stack frame for the callee, argument passing, - * and control transfer to the target function address. + * The CALL instruction transfers control to a subroutine at the given address, + * passing arguments from the operand stack to a new local variable store. *

                                                    * - * @param parts The instruction parameters. Must include: - *
                                                      - *
                                                    • {@code parts[0]}: The "CALL" operator.
                                                    • - *
                                                    • {@code parts[1]}: The target address of the callee function.
                                                    • - *
                                                    • {@code parts[2]}: The number of arguments to pass.
                                                    • - *
                                                    - * @param currentPC The current program counter, used to record the return address for after the call. - * @param operandStack The operand stack manager. Arguments are popped from this stack. - * @param callerLVS The local variable store of the caller function (not directly modified here). - * @param callStack The virtual machine's call stack manager, used to push the new stack frame. - * @return The new program counter value, which is the address of the callee function (i.e., jump target). - * The VM should transfer control to this address after setting up the call frame. - * @throws IllegalArgumentException If the instruction parameters are malformed or missing. - * @throws IllegalStateException If the operand stack does not contain enough arguments. + * @param parts the parts of the instruction; expects: [CALL, targetAddress, nArgs] + * @param currentPC the current program counter (PC) + * @param operandStack the VM's operand stack (used for passing arguments) + * @param ignoredCallerLVS the local variable store of the caller (unused in this implementation) + * @param callStack the VM's call stack (where new frames are pushed) + * @return the target address to transfer control to (i.e., jump to) + * @throws IllegalStateException if the instruction format is invalid */ @Override public int execute(String[] parts, int currentPC, OperandStack operandStack, - LocalVariableStore callerLVS, + LocalVariableStore /* caller LVT, unused */ ignoredCallerLVS, CallStack callStack) { - if (parts.length < 3) - throw new IllegalArgumentException("CALL: need "); + // 1. Validate instruction arguments. + if (parts.length < 3) { + throw new IllegalStateException("CALL requires 2 operands: target and nArgs"); + } - /* ----------- Parse target address / method signature ----------- */ - final String targetToken = parts[1]; // Can be a numeric address or "@Class::method" - final int nArgs = Integer.parseInt(parts[2]); + final String rawTarget = parts[1].trim(); + final int nArgs = Integer.parseInt(parts[2].trim()); - /* ----------- Build callee's local variable store ----------- */ - LocalVariableStore calleeLVS = new LocalVariableStore(); - for (int slot = nArgs - 1; slot >= 0; slot--) { - if (operandStack.isEmpty()) - throw new IllegalStateException("CALL: operand stack underflow"); - calleeLVS.setVariable(slot, operandStack.pop()); + // 2. Pop arguments from the operand stack and restore left-to-right order. + // Arguments are pushed left-to-right, so we pop them and reverse into the args array. + final Object[] args = new Object[nArgs]; + for (int i = nArgs - 1; i >= 0; i--) { + args[i] = operandStack.pop(); } - /* ----------- Handle virtual call ----------- */ - int targetAddr; - if (targetToken.startsWith("@")) { // "@Class::method" convention indicates a virtual call - Object thisRef = calleeLVS.getVariable(0); // By convention, slot-0 stores "this" - if (!(thisRef instanceof Instance inst)) - throw new IllegalStateException("VCALL: slot-0 is not an object reference"); + // 3. Resolve the target address for the subroutine (currently supports only static calls). + int targetAddr = Integer.parseInt(rawTarget); + String methodNameForCtx = "subroutine@" + targetAddr; + print("\nCALL -> " + targetAddr); - String methodSig = targetToken.substring(1); // Remove '@' - targetAddr = inst.vtable().lookup(methodSig); - } else { - /* Direct/static call (numeric address) */ - targetAddr = Integer.parseInt(targetToken); + // 4. Build the callee's local variable store and copy arguments into it. + LocalVariableStore calleeLVS = new LocalVariableStore(); + for (int i = 0; i < nArgs; i++) { + calleeLVS.setVariable(i, args[i]); } - /* ----------- Push new stack frame and jump ----------- */ + // 5. Create a new stack frame for the callee and push it onto the call stack. + // The return address is set to the next instruction after CALL. StackFrame newFrame = new StackFrame( currentPC + 1, calleeLVS, - new MethodContext("subroutine@" + targetAddr, null) + new MethodContext(methodNameForCtx, null) // Don't log full args to avoid heavy logs ); callStack.pushFrame(newFrame); - print("\nCalling function at address: " + targetAddr); - return targetAddr; // jump + // 6. Transfer control to the target address (subroutine entry point). + return targetAddr; } } diff --git a/src/main/java/org/jcnc/snow/vm/module/Instance.java b/src/main/java/org/jcnc/snow/vm/module/Instance.java deleted file mode 100644 index 87412e82..00000000 --- a/src/main/java/org/jcnc/snow/vm/module/Instance.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.jcnc.snow.vm.module; - -import java.util.HashMap; -import java.util.Map; - -/** - * The {@code Instance} class represents a runtime object instance - * in the virtual machine. - *

                                                    - * Each instance maintains: - *

                                                      - *
                                                    • A reference to its {@link VirtualTable} (vtable), which provides - * dynamic method dispatch and runtime method lookup.
                                                    • - *
                                                    • A map of field values, where each field is identified by name - * and can hold an arbitrary object reference.
                                                    • - *
                                                    - * - *

                                                    Key responsibilities:

                                                    - *
                                                      - *
                                                    • Encapsulate the runtime state of an object.
                                                    • - *
                                                    • Enable field storage and retrieval through {@link #setField(String, Object)} - * and {@link #getField(String)}.
                                                    • - *
                                                    • Provide access to the instance’s virtual table for method resolution.
                                                    • - *
                                                    - */ -public final class Instance { - - /** - * The virtual table associated with this instance (immutable). - */ - private final VirtualTable vtable; - - /** - * A mapping of field names to their runtime values. - */ - private final Map fields = new HashMap<>(); - - /** - * Constructs a new {@code Instance} with the specified virtual table. - * - * @param vtable The virtual table that defines the method dispatch behavior - * for this instance. Must not be {@code null}. - */ - public Instance(VirtualTable vtable) { - this.vtable = vtable; - } - - /* ---------- Virtual Table ---------- */ - - /** - * Returns the virtual table associated with this instance. - *

                                                    - * The virtual table is used for runtime method resolution - * (dynamic dispatch). - *

                                                    - * - * @return The {@link VirtualTable} of this instance. - */ - public VirtualTable vtable() { - return vtable; - } - - /* ---------- Fields ---------- */ - - /** - * Sets the value of a field in this instance. - *

                                                    - * If the field does not already exist, it is created. - * If the field exists, its value is overwritten. - *

                                                    - * - * @param name The name of the field to set. Must not be {@code null}. - * @param value The value to assign to the field. Can be {@code null}. - */ - public void setField(String name, Object value) { - fields.put(name, value); - } - - /** - * Retrieves the value of a field in this instance. - *

                                                    - * The value is cast to the expected type at runtime. - * If the field is not present, this method returns {@code null}. - *

                                                    - * - * @param name The name of the field to retrieve. Must not be {@code null}. - * @param The expected type of the field value. - * @return The field value cast to type {@code T}, or {@code null} if absent. - * @throws ClassCastException If the stored value cannot be cast to {@code T}. - */ - @SuppressWarnings("unchecked") - public T getField(String name) { - return (T) fields.get(name); - } -} diff --git a/src/main/java/org/jcnc/snow/vm/module/LocalVariableStore.java b/src/main/java/org/jcnc/snow/vm/module/LocalVariableStore.java index 2904d04a..47d9fca9 100644 --- a/src/main/java/org/jcnc/snow/vm/module/LocalVariableStore.java +++ b/src/main/java/org/jcnc/snow/vm/module/LocalVariableStore.java @@ -9,70 +9,113 @@ import java.util.ArrayList; import static org.jcnc.snow.vm.utils.VMUtils.isNativeImage; /** - * The {@code LocalVariableStore} represents a simple dynamically-sized - * local-variable table (frame locals) of the VM. + * The {@code LocalVariableStore} represents a simple, dynamically-sized + * local-variable table (frame locals) for the virtual machine (VM). * - *

                                                    It supports random access via {@link #setVariable(int, Object)} - * / {@link #getVariable(int)} and can compact itself - * by trimming trailing {@code null} slots after execution has finished.

                                                    + *

                                                    This class supports random access for storing and retrieving variables + * via {@link #setVariable(int, Object)} and {@link #getVariable(int)}. + * It can also compact itself by trimming trailing {@code null} + * slots after execution, for cleaner debug output. + * + *

                                                    Internally, it uses an {@link ArrayList} to store variables, automatically + * expanding as needed to support random index writes. This structure is designed + * for VM stack frame management and debug inspection. */ public class LocalVariableStore { + /** + * The backing list storing the local variables. + */ private final ArrayList localVariables; - /* ---------- construction ---------- */ + /* ---------- Construction ---------- */ + + /** + * Constructs a new {@code LocalVariableStore} with the given initial capacity. + * + * @param initialCapacity the initial capacity for the local variable list + */ public LocalVariableStore(int initialCapacity) { this.localVariables = new ArrayList<>(initialCapacity); handleMode(); } + /** + * Constructs a new {@code LocalVariableStore} with default capacity. + */ public LocalVariableStore() { this.localVariables = new ArrayList<>(); handleMode(); } - /* ---------- public API ---------- */ + /* ---------- Public API ---------- */ /** - * Sets the value at {@code index}, expanding the list if necessary. + * Sets the value at the specified index, expanding the list if necessary. + *

                                                    If the list is smaller than {@code index + 1}, it will be padded + * with {@code null} until the required capacity is reached. + * + * @param index the index to set (0-based) + * @param value the value to store at the specified index + * @throws IndexOutOfBoundsException if {@code index} is negative */ public void setVariable(int index, Object value) { ensureCapacity(index + 1); localVariables.set(index, value); } - /* ------------------------------------------------------------ - * Backward compatibility: VM instruction decoder can directly call - * store / load methods without caring about internal naming differences. - * ------------------------------------------------------------ */ + /** + * Stores a value at the specified index (alias for {@link #setVariable}). + *

                                                    This method is provided for VM instruction decoder compatibility. + * + * @param index the index to set + * @param value the value to store + */ public void store(int index, Object value) { setVariable(index, value); } + /** + * Loads the value from the specified index (alias for {@link #getVariable}). + *

                                                    This method is provided for VM instruction decoder compatibility. + * + * @param index the index to retrieve + * @return the value at the given index + */ public Object load(int index) { return getVariable(index); } /** - * Returns the value at {@code index}. + * Returns the value at the specified index. + *

                                                    If the list is not large enough, it is automatically expanded, + * filling new slots with {@code null} values. + * + * @param index the index to retrieve (0-based) + * @return the value at the specified index, or {@code null} if not set + * @throws IndexOutOfBoundsException if {@code index} is negative */ public Object getVariable(int index) { - /* 修改点 #1 —— 自动扩容以避免 LOAD 越界异常 */ + // Automatic expansion to avoid LOAD out-of-bounds exception. if (index < 0) throw new IndexOutOfBoundsException("Negative LV index: " + index); ensureCapacity(index + 1); - return localVariables.get(index); // 可能为 null,符合 JVM 语义 + return localVariables.get(index); } /** - * Exposes the backing list (read-only preferred). + * Returns the backing {@link ArrayList} storing the local variables. + *

                                                    Direct modification is not recommended. Prefer read-only usage. + * + * @return the internal list of local variables */ public ArrayList getLocalVariables() { return localVariables; } /** - * Prints every slot to the logger. + * Prints the contents of each slot in the local variable table to the logger. + *

                                                    If the table is empty, a corresponding message is printed instead. */ public void printLv() { if (localVariables.isEmpty()) { @@ -86,24 +129,23 @@ public class LocalVariableStore { } } - - /* ---------- internal helpers ---------- */ + /* ---------- Internal Helpers ---------- */ /** - * Clears all variables (used when a stack frame is popped). + * Clears all variables in the table. + *

                                                    This method is typically called when a stack frame is popped. */ public void clearVariables() { localVariables.clear(); } /** - * Compacts the table by removing trailing {@code null} slots. - *

                                                    Call this once after program termination (e.g. in - * {@code VirtualMachineEngine.execute()} before printing) to get - * cleaner debug output without affecting execution-time indices.

                                                    + * Compacts the table by removing only trailing {@code null} slots. + *

                                                    This should be called after program termination, for cleaner debug output. + * Does not affect non-null slots or internal indices during execution. */ public void compact() { - /* 修改点 #2 —— 仅删除“尾部” null,而不是整表过滤 */ + // Only delete the "tail" null values, not filter the entire table. int i = localVariables.size() - 1; while (i >= 0 && localVariables.get(i) == null) { localVariables.remove(i); @@ -112,22 +154,22 @@ public class LocalVariableStore { } /** - * Ensures backing list can hold {@code minCapacity} slots. + * Ensures that the backing list has at least the specified minimum capacity. + *

                                                    New slots are filled with {@code null} values if the list needs to grow. + * + * @param minCapacity the minimum capacity required */ private void ensureCapacity(int minCapacity) { - /* 修改点 #3 —— 使用 while 循环填充 null,确保 slot 可随机写入 */ while (localVariables.size() < minCapacity) { localVariables.add(null); } } /** - * Mode-specific UI hook for debugging. - *

                                                    - * If debug mode is enabled and not running inside a GraalVM native-image, - * this method will open the Swing-based variable inspector window. - * In native-image environments (where AWT/Swing is unavailable), - * the window will not be displayed. + * Handles debug mode hooks. If debug mode is enabled and not running inside a + * GraalVM native-image, this method will open a Swing-based variable inspector + * window for debugging purposes. + *

                                                    In native-image environments, this window is not displayed. */ private void handleMode() { if (SnowConfig.isDebug()) { diff --git a/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java b/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java deleted file mode 100644 index 7ecda570..00000000 --- a/src/main/java/org/jcnc/snow/vm/module/VirtualTable.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.jcnc.snow.vm.module; - -import java.util.HashMap; -import java.util.Map; - -/** - * The {@code VirtualTable} class represents a runtime virtual function table (vtable) - * used by the virtual machine to support dynamic method dispatch. - *

                                                    - * A vtable is a mapping from method signatures to their corresponding - * entry addresses in the VM code segment. Each class or instance can have - * its own vtable that determines which concrete method implementations - * are invoked at runtime. - *

                                                    - * - *

                                                    Key details:

                                                    - *
                                                      - *
                                                    • Key: A method signature, such as {@code "Person::getName"}.
                                                    • - *
                                                    • Value: The entry point address of the method implementation - * within the VM code segment.
                                                    • - *
                                                    - */ -public final class VirtualTable { - - /** - * Mapping from method signature to its entry address in the VM code segment. - */ - private final Map table = new HashMap<>(); - - /** - * Registers a new method implementation in the virtual table, or overrides - * an existing entry if the method signature is already present. - * - * @param methodSig The method signature (e.g., {@code "Person::getName"}). - * @param addr The entry address of the method implementation in the VM code segment. - */ - public void register(String methodSig, int addr) { - table.put(methodSig, addr); - } - - /** - * Looks up the entry address for the given method signature. - *

                                                    - * If the method is not found in the virtual table, an {@link IllegalStateException} - * is thrown to aid debugging. - *

                                                    - * - * @param methodSig The method signature to look up. - * @return The entry address of the corresponding method implementation. - * @throws IllegalStateException If no mapping exists for the given method signature. - */ - public int lookup(String methodSig) { - Integer addr = table.get(methodSig); - if (addr == null) - throw new IllegalStateException("VTable missing entry: " + methodSig); - return addr; - } - - /** - * Returns a read-only snapshot of the current virtual table. - *

                                                    - * This is primarily intended for debugging or inspection purposes, - * allowing external code to see the current state of the vtable - * without modifying it. - *

                                                    - * - * @return An unmodifiable copy of the method signature to entry address mappings. - */ - public Map snapshot() { - return Map.copyOf(table); - } -} -- Gitee From 9b710abb5e78834a48bc4ae8eb1878ea219b50f9 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 11:57:28 +0800 Subject: [PATCH 10/19] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0README=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=AD=E7=9A=84=E6=89=A7=E8=A1=8C=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=92=8C=E6=A0=B8=E5=BF=83=E5=8A=9F=E8=83=BD=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了`Instance`与`VirtualTable`相关的详细说明 --- src/main/java/org/jcnc/snow/vm/doc/README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jcnc/snow/vm/doc/README.md b/src/main/java/org/jcnc/snow/vm/doc/README.md index 07f14a4f..ac5bb164 100644 --- a/src/main/java/org/jcnc/snow/vm/doc/README.md +++ b/src/main/java/org/jcnc/snow/vm/doc/README.md @@ -8,8 +8,8 @@ 它采用**命令(Command)模式 + 统一操作码表(`VMOpCode`)+ 工厂注册(`CommandFactory`)**的结构,配合**运行时栈/局部变量表/调用栈 **与**方法栈帧**,构成清晰可扩展的执行层。 -执行流程:`VMLauncher/VMInitializer` 解析指令文件 → `CommandLoader` 读入并清洗文本 → `VirtualMachineEngine` 主循环按 **PC -** 逐条解释执行(跳过空行与 `#` 注释),通过 `CommandExecutionHandler` 分发到各具体指令类,直到 `RET`(根帧)或 `HALT` 正常终止。 +执行流程:`VMLauncher/VMInitializer` 解析指令文件 → `CommandLoader` 读入并清洗文本 → `VirtualMachineEngine` 主循环按 PC +逐条解释执行(跳过空行与 `#` 注释),通过 `CommandExecutionHandler` 分发到各具体指令类,直到 `RET`(根帧)或 `HALT` 正常终止。 ## 核心功能 @@ -43,12 +43,11 @@ * **栈操作**:`PopCommand`(`POP`)、`DupCommand`(`DUP`)、`SwapCommand`(`SWAP`) * **寄存器移动**:`MovCommand`(`MOV src,dst`,在同一局部变量表内复制槽位) -* **引用/对象与虚方法支持** +* **引用/对象支持** * 引用操作:`R_PUSH / R_LOAD / R_STORE`(分别用于将引用压栈、从局部变量表加载/存储引用) * 运行时模型: * `module.StackFrame`(保存返回地址、`LocalVariableStore`、`OperandStack`、`MethodContext`) * `module.CallStack`(带上限保护的调用栈) - * `module.Instance`、`module.VirtualTable`(vtable:方法签名 → 入口地址,支持动态分派) * **系统调用与 I/O** * 统一入口:`SyscallCommand`(`SYSCALL`),失败时约定**向栈压 `-1`** @@ -106,9 +105,7 @@ vm/ │ ├── LocalVariableStore // 局部变量表(自动扩容/紧凑化) │ ├── CallStack // 调用栈(含深度保护) │ ├── StackFrame // 栈帧:返回地址 + 局部表 + 栈 + 方法元信息 - │ ├── MethodContext // 方法上下文(名称/实参,用于调试) - │ ├── Instance // 对象实例占位 - │ └── VirtualTable // vtable:方法签名 → 入口地址 + │ └── MethodContext // 方法上下文(名称/实参,用于调试) │ ├── io/ // I/O 与文件系统桥接 │ ├── FDTable // 虚拟 fd ↔ NIO Channel 映射(含 0/1/2) -- Gitee From 4d8372df4c52c40893a25661449f9d2fb926e61b Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 15:16:39 +0800 Subject: [PATCH 11/19] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20Signatur?= =?UTF-8?q?eRegistrar=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../semantic/core/SignatureRegistrar.java | 129 +++++++++++------- 1 file changed, 76 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/SignatureRegistrar.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/SignatureRegistrar.java index 71e6cb4e..38d1dfc7 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/SignatureRegistrar.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/SignatureRegistrar.java @@ -12,49 +12,66 @@ import java.util.List; import java.util.Optional; /** - * {@code SignatureRegistrar} + * {@code SignatureRegistrar} 是语义分析前置阶段的注册器。 *

                                                    - * 语义分析准备阶段:负责函数签名登记、结构体签名登记与 import 校验。 + * 它负责函数签名登记、结构体签名登记以及 import 模块引用校验, + * 为后续的类型推断和语义分析建立完整的类型环境。 * + *

                                                    本类通过三阶段处理逻辑,确保跨模块引用和继承在类型推断时可用: + *

                                                      + *
                                                    1. 校验模块的 import 是否存在,并预注册结构体的名称占位符。
                                                    2. + *
                                                    3. 解析结构体字段、构造函数和方法的签名信息。
                                                    4. + *
                                                    5. 处理结构体继承关系,并继承字段与方法。
                                                    6. + *
                                                    + *

                                                    错误处理策略: *

                                                      - *
                                                    • 验证每个模块声明的 import 模块在全局模块表 {@link Context#modules()} 是否存在。
                                                    • - *
                                                    • 将每个函数、结构体方法、构造函数的类型签名登记到 {@link ModuleInfo},便于后续类型推断。
                                                    • - *
                                                    • 支持 {@code extends} 单继承:子类会继承父类的字段与方法。
                                                    • - *
                                                    • 若参数或返回类型无法解析,则报错并降级为 int 或 void,保证语义分析流程健壮。
                                                    • + *
                                                    • 若引用未知模块、类型或父类,均会记录为 {@link SemanticError} 错误。
                                                    • + *
                                                    • 若字段、参数、返回类型无法解析,将默认降级为 {@code int} 或 {@code void} 类型以保证流程健壮性。
                                                    • *
                                                    - *

                                                    - * 作为语义分析前置流程,为后续函数体和表达式分析提供类型环境。 + * + * @param ctx 语义分析上下文,记录所有模块、类型信息与错误列表 */ public record SignatureRegistrar(Context ctx) { /** - * 遍历所有模块,注册函数/方法/结构体签名,校验 import 合法性。 + * 注册传入的所有模块的类型签名信息,包括 import 检查、结构体与函数签名建立。 + *

                                                    + * 采用三阶段设计确保跨模块结构体引用/继承不会出错。 * - * @param modules 需要分析的所有模块列表(AST 顶层节点) + * @param modules 所有模块 AST 节点列表 */ public void register(Iterable modules) { + // 第一阶段:验证模块 imports 与预注册结构体名称 for (ModuleNode mod : modules) { - ctx.setCurrentModule(mod.name()); // 切换上下文到当前模块 + ctx.setCurrentModule(mod.name()); ModuleInfo mi = ctx.modules().get(mod.name()); - // ========== 1) 校验 imports ========== + // 检查 import 的模块是否存在 for (ImportNode imp : mod.imports()) { if (!ctx.modules().containsKey(imp.moduleName())) { - // 导入的模块在全局表中不存在,报错 ctx.errors().add(new SemanticError(imp, "未知模块: " + imp.moduleName())); } else { - // 添加到本模块导入集合 mi.getImports().add(imp.moduleName()); } } - // ========== 2) 结构体签名登记 ========== + // 为每个 struct 创建占位 StructType(无字段/方法) for (StructNode stn : mod.structs()) { - // 构造结构体类型对象,唯一标识为 (模块名, 结构体名) - StructType st = new StructType(mod.name(), stn.name()); - mi.getStructs().put(stn.name(), st); + if (!mi.getStructs().containsKey(stn.name())) { + mi.getStructs().put(stn.name(), new StructType(mod.name(), stn.name())); + } + } + } - // --- 2.0 字段签名登记 --- + // 第二阶段:解析 struct 字段、构造函数与方法签名 + for (ModuleNode mod : modules) { + ctx.setCurrentModule(mod.name()); + ModuleInfo mi = ctx.modules().get(mod.name()); + + for (StructNode stn : mod.structs()) { + StructType st = mi.getStructs().get(stn.name()); + + // 2.0 解析字段类型 if (stn.fields() != null) { for (DeclarationNode field : stn.fields()) { Type ft = ctx.parseType(field.getType()); @@ -66,12 +83,11 @@ public record SignatureRegistrar(Context ctx) { } } - // --- 2.1 多个构造函数 init(重载,按参数个数区分) --- + // 2.1 注册构造函数类型(参数列表 -> void) if (stn.inits() != null) { for (FunctionNode initFn : stn.inits()) { List ptypes = new ArrayList<>(); for (ParameterNode p : initFn.parameters()) { - // 解析参数类型,不存在则报错降级为 int Type t = ctx.parseType(p.type()); if (t == null) { ctx.errors().add(new SemanticError(p, "未知类型: " + p.type())); @@ -79,12 +95,11 @@ public record SignatureRegistrar(Context ctx) { } ptypes.add(t); } - // 构造函数返回类型固定为 void st.addConstructor(new FunctionType(ptypes, BuiltinType.VOID)); } } - // --- 2.2 方法签名 --- + // 2.2 注册方法签名 for (FunctionNode fn : stn.methods()) { List ptypes = new ArrayList<>(); for (ParameterNode p : fn.parameters()) { @@ -100,32 +115,38 @@ public record SignatureRegistrar(Context ctx) { st.getMethods().put(fn.name(), new FunctionType(ptypes, ret)); } } + } + + // 第三阶段:解析并建立 struct 的继承关系 + for (ModuleNode mod : modules) { + ctx.setCurrentModule(mod.name()); + ModuleInfo mi = ctx.modules().get(mod.name()); - // ========== 2.3 继承处理 ========== for (StructNode stn : mod.structs()) { - if (stn.parent() != null) { - StructType child = mi.getStructs().get(stn.name()); - StructType parent = resolveParentStruct(mi, stn.parent()); - - if (parent == null) { - // 父类不存在(既不在本模块,也不在导入模块 / 限定名错误),报语义错误 - ctx.errors().add(new SemanticError(stn, "未知父类: " + stn.parent())); - } else { - // 建立继承链 - child.setParent(parent); - - // 继承字段 - parent.getFields().forEach( - (k, v) -> child.getFields().putIfAbsent(k, v)); - // 继承方法 - parent.getMethods().forEach( - (k, v) -> child.getMethods().putIfAbsent(k, v)); - // 构造函数不继承 - } + if (stn.parent() == null) continue; + StructType child = mi.getStructs().get(stn.name()); + StructType parent = resolveParentStruct(mi, stn.parent()); + + if (parent == null) { + ctx.errors().add(new SemanticError(stn, "未知父类: " + stn.parent())); + continue; } + + // 建立父子继承关系 + child.setParent(parent); + // 继承字段(若未重写) + parent.getFields().forEach((k, v) -> child.getFields().putIfAbsent(k, v)); + // 继承方法(若未重写) + parent.getMethods().forEach((k, v) -> child.getMethods().putIfAbsent(k, v)); + // 构造函数不继承 } + } + + // 第四阶段:注册模块顶层函数签名 + for (ModuleNode mod : modules) { + ctx.setCurrentModule(mod.name()); + ModuleInfo mi = ctx.modules().get(mod.name()); - // ========== 3) 模块级函数签名登记 ========== for (FunctionNode fn : mod.functions()) { List params = new ArrayList<>(); for (ParameterNode p : fn.parameters()) { @@ -144,14 +165,16 @@ public record SignatureRegistrar(Context ctx) { } /** - * 解析父类结构体: - *

                                                      - *
                                                    • 支持限定名 {@code Module.Struct}。
                                                    • - *
                                                    • 支持在本模块与 import 的模块中按未限定名查找。
                                                    • - *
                                                    + * 解析父类结构体类型。 + *

                                                    支持限定名形式(如 {@code Module.Struct}), + * 也支持在当前模块或导入模块中查找非限定名结构体。 + * + * @param mi 当前模块信息 + * @param parentName 父类名称(可以是限定名或非限定名) + * @return 对应的 StructType,找不到则返回 null */ private StructType resolveParentStruct(ModuleInfo mi, String parentName) { - // 1. 限定名:Module.Struct + // 限定名:Module.Struct int dot = parentName.indexOf('.'); if (dot > 0 && dot < parentName.length() - 1) { String m = parentName.substring(0, dot); @@ -163,11 +186,11 @@ public record SignatureRegistrar(Context ctx) { return null; } - // 2. 先在当前模块找 + // 当前模块中查找 StructType local = mi.getStructs().get(parentName); if (local != null) return local; - // 3. 在导入模块中找 + // 导入模块中查找 for (String imported : mi.getImports()) { ModuleInfo pim = ctx.modules().get(imported); if (pim == null) continue; @@ -175,7 +198,7 @@ public record SignatureRegistrar(Context ctx) { if (st != null) return st; } - // 未找到 + // 均找不到 return null; } } -- Gitee From 456fd48aa42184a1ce54c3bae567e2270e405224 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 16:59:36 +0800 Subject: [PATCH 12/19] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=20IRBuilde?= =?UTF-8?q?rScope=20=E7=B1=BB=E7=BB=93=E6=9E=84=E5=92=8C=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新类文档,明确 IRBuilderScope 的主要职责 - 优化方法文档,提高文档的准确性和可读性 - 删除冗余代码和不必要的注释 - 调整代码结构,按功能分组相关方法 --- .../ir/builder/core/IRBuilderScope.java | 169 +++++++----------- 1 file changed, 60 insertions(+), 109 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java index 4df33b4d..61dad7f1 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/core/IRBuilderScope.java @@ -8,14 +8,13 @@ import java.util.HashMap; import java.util.Map; /** - * {@code IRBuilderScope} 用于管理单个函数作用域内的变量名与虚拟寄存器的映射关系。 + * {@code IRBuilderScope} 用于管理单个函数作用域内的变量名与虚拟寄存器的映射关系,以及相关类型、常量信息和结构体元数据。 *

                                                    - * 主要职责: + * 主要职责包括: *

                                                      - *
                                                    • 维护当前作用域内所有已声明变量的寄存器和类型信息
                                                    • + *
                                                    • 维护当前作用域内所有已声明变量的虚拟寄存器和类型信息
                                                    • *
                                                    • 支持变量与虚拟寄存器的重新绑定与查找
                                                    • - *
                                                    • 支持变量的类型信息记录与查询
                                                    • - *
                                                    • 支持变量的编译期常量值记录与查询(便于常量折叠等优化)
                                                    • + *
                                                    • 支持变量类型和编译期常量值的记录与查询
                                                    • *
                                                    • 支持跨模块全局常量(如 ModuleA.a)查找
                                                    • *
                                                    • 维护结构体字段布局(全局共享):字段名 → 槽位下标,用于对象字段读写
                                                    • *
                                                    • 维护结构体继承关系(子类 → 父类),super(...) 调用会用到
                                                    • @@ -24,15 +23,15 @@ import java.util.Map; public final class IRBuilderScope { /** - * 结构体字段布局表:结构体名 → (字段名 → 槽位下标) + * 结构体字段布局表(全局共享):结构体名 → (字段名 → 槽位下标) */ private static final Map> STRUCT_LAYOUTS = new HashMap<>(); /** - * 结构体继承关系表:子类名 → 父类名 + * 结构体继承关系表(全局共享):子类名 → 父类名 */ private static final Map STRUCT_PARENTS = new HashMap<>(); /** - * 变量名到虚拟寄存器的映射表(本地变量) + * 变量名到虚拟寄存器的映射表(本地变量,仅当前作用域) */ private final Map vars = new HashMap<>(); /** @@ -52,27 +51,25 @@ public final class IRBuilderScope { */ private IRFunction fn; - // ---------------- 作用域与变量 ---------------- + // ---------------- 结构体全局布局/继承 注册与查询 ---------------- /** - * 全局注册结构体的字段布局映射(字段名 -> 槽位下标)。 - * 一般在语义分析/IR 前期由类型系统收集后调用。 + * 注册结构体字段布局。注册后该结构体名对应的字段布局会被全局保存。 * - * @param structName 结构体名(建议为简单名,如 "Animal";如有模块前缀也可) - * @param fieldToIndex 字段名到下标的映射(下标从 0 递增) + * @param structName 结构体名 + * @param fieldToIndex 字段名到槽位下标的映射表 */ static void registerStructLayout(String structName, Map fieldToIndex) { if (structName == null || fieldToIndex == null) return; - // 覆盖式注册:方便增量/重复编译时刷新 STRUCT_LAYOUTS.put(structName, new HashMap<>(fieldToIndex)); } /** - * 读取某结构体的完整字段布局(返回只读 Map)。 - * 支持“模块.结构体”及简单名两种写法。 + * 获取结构体的字段布局。 + * 支持全限定名与简单名查找。 * - * @param structName 结构体名 - * @return 字段名到下标映射的只读视图,或 null + * @param structName 结构体名或全限定名 + * @return 字段名到槽位下标的不可变映射表;若未注册则返回 null */ public static Map getStructLayout(String structName) { Map layout = STRUCT_LAYOUTS.get(structName); @@ -86,15 +83,10 @@ public final class IRBuilderScope { } /** - * 注册结构体的父类信息。 - *

                                                      - * 该方法用于维护结构体与其父类之间的映射关系。通过调用此方法, - * 可以为某个结构体名称指定其父结构体名称,并保存到全局的 - * {@code STRUCT_PARENTS} 映射中。 - *

                                                      + * 注册结构体继承关系。 * - * @param structName 子结构体的名称,不能为空或 {@code null} - * @param parentName 父结构体的名称,不能为空、不能为 {@code null} 或空白 + * @param structName 子类名 + * @param parentName 父类名 */ static void registerStructParent(String structName, String parentName) { if (structName == null || parentName == null || parentName.isBlank()) return; @@ -102,24 +94,10 @@ public final class IRBuilderScope { } /** - * 获取某个结构体的父结构体名称。 - *

                                                      - * 查询逻辑如下: - *

                                                        - *
                                                      1. 首先直接从 {@code STRUCT_PARENTS} 中查找对应的父结构体。
                                                      2. - *
                                                      3. 如果未找到,且 {@code structName} 含有点号(.),则提取点号后的简单类名进行查找。
                                                      4. - *
                                                      5. 如果仍未找到,则遍历 {@code STRUCT_PARENTS} 的所有条目: - *
                                                          - *
                                                        • 检查键(key)是否包含点号,若存在,则取其最后一个点号后的子串作为简单类名。
                                                        • - *
                                                        • 如果该简单类名与传入的 {@code structName} 相等,则返回对应的父类名称。
                                                        • - *
                                                        - *
                                                      6. - *
                                                      7. 如果所有方式都未找到,则返回 {@code null}。
                                                      8. - *
                                                      - *

                                                      + * 获取结构体父类名。支持全限定名和简单名的模糊查找。 * - * @param structName 需要查找父类的结构体名称,可以是完整类名或简单类名 - * @return 父结构体名称;如果未找到,返回 {@code null} + * @param structName 结构体名 + * @return 父类名;如果未注册或无父类则返回 null */ public static String getStructParent(String structName) { if (structName == null || structName.isBlank()) return null; @@ -143,93 +121,93 @@ public final class IRBuilderScope { return null; } + // ---------------- 作用域绑定 & 变量声明 ---------------- + /** - * 绑定当前作用域到指定 IRFunction。 + * 绑定当前作用域至指定 IRFunction 对象。 + * 后续变量声明、寄存器分配依赖于该函数上下文。 * - * @param fn 目标 IRFunction + * @param fn 待绑定的 IRFunction 实例 */ void attachFunction(IRFunction fn) { this.fn = fn; } /** - * 声明一个新变量并分配新的虚拟寄存器。 + * 声明一个新变量,分配虚拟寄存器并记录类型。 + * 同名变量会被覆盖。 * - * @param name 变量名称 - * @param type 变量类型名 + * @param name 变量名 + * @param type 变量类型字符串 */ public void declare(String name, String type) { IRVirtualRegister reg = fn.newRegister(); vars.put(name, reg); varTypes.put(name, type); - varConstValues.remove(name); // 声明新变量即清除原常量绑定 + varConstValues.remove(name); } /** - * 声明新变量,并绑定到指定的寄存器。 + * 声明一个新变量,指定虚拟寄存器并记录类型。 + * 用于特殊情况(如参数寄存器直接传入)。 * - * @param name 变量名称 - * @param type 变量类型名 - * @param reg 绑定的虚拟寄存器 + * @param name 变量名 + * @param type 变量类型字符串 + * @param reg 指定的虚拟寄存器 */ public void declare(String name, String type, IRVirtualRegister reg) { vars.put(name, reg); varTypes.put(name, type); - varConstValues.remove(name); // 重复声明也会清除常量绑定 + varConstValues.remove(name); } - // ---------------- 编译期常量 ---------------- - /** - * 更新变量的虚拟寄存器绑定(如变量已存在则覆盖,否则等同于新声明)。 + * 更新指定变量所绑定的虚拟寄存器。 + * 不改变类型信息。 * - * @param name 变量名称 - * @param reg 新的虚拟寄存器 + * @param name 变量名 + * @param reg 新虚拟寄存器 */ void put(String name, IRVirtualRegister reg) { vars.put(name, reg); } /** - * 查找变量名对应的虚拟寄存器。 + * 查找变量对应的虚拟寄存器。 * * @param name 变量名 - * @return 已绑定的虚拟寄存器,若未声明则返回 null + * @return 虚拟寄存器;不存在则返回 null */ public IRVirtualRegister lookup(String name) { return vars.get(name); } /** - * 查找变量名对应的类型名。 + * 查找变量的类型字符串。 * * @param name 变量名 - * @return 已声明类型字符串,若未声明则返回 null + * @return 类型字符串;不存在则返回 null */ public String lookupType(String name) { return varTypes.get(name); } - // ---------------- 跨模块常量导入支持 ---------------- - /** - * 获取变量名到类型名映射的不可变副本。 + * 获取当前作用域下所有变量的类型信息。 * - * @return 变量名→类型名映射的只读视图(用于调试/全局分析) + * @return 不可变映射表:变量名 → 类型字符串 */ public Map getVarTypes() { return Collections.unmodifiableMap(varTypes); } - // ---------------- 结构体字段布局(全局静态) ---------------- + // ---------------- 编译期常量与导入 ---------------- /** - * 设置变量的编译期常量值(本地变量)。 - *

                                                      - * 便于 IR 生成时做常量折叠等优化,value 传 null 则清除绑定。 + * 设置变量的编译期常量值。value=null 时将移除常量绑定。 * - * @param name 变量名称 - * @param value 常量值(null 表示清除) + * @param name 变量名 + * @param value 常量值对象;null 表示移除 */ public void setConstValue(String name, Object value) { if (value == null) varConstValues.remove(name); @@ -237,61 +215,34 @@ public final class IRBuilderScope { } /** - * 获取变量的编译期常量值(优先本地,再查跨模块导入)。 - *

                                                      - * 常用于优化与折叠,支持 "Module.a" 这类跨模块全局常量查找。 + * 获取变量的编译期常量值。 + * 若当前作用域未绑定,则查找导入的全局常量。 * - * @param name 变量名称或"模块名.常量名" - * @return 编译期常量值,或 null + * @param name 变量名(或导入常量名) + * @return 常量值对象;不存在则返回 null */ public Object getConstValue(String name) { Object v = varConstValues.get(name); if (v != null) return v; - // 支持跨模块常量/全局变量(如 "ModuleA.a") return externalConsts.get(name); } /** - * 清除变量的编译期常量值绑定(本地)。 + * 清除变量的编译期常量值绑定。 * - * @param name 变量名称 + * @param name 变量名 */ public void clearConstValue(String name) { varConstValues.remove(name); } - // ---------------- 结构体继承关系 ---------------- - /** - * 导入外部(其他模块)的全局常量/变量。 + * 导入外部模块的全局常量。 * - * @param qualifiedName 形如 "ModuleA.a" - * @param value 其常量值 + * @param qualifiedName 全限定名(如 ModuleA.a) + * @param value 常量值对象 */ public void importExternalConst(String qualifiedName, Object value) { externalConsts.put(qualifiedName, value); } - - /** - * 查询字段槽位下标。 - * 支持“模块.结构体”及简单名两种写法自动兼容。 - * - * @param structName 结构体名("Module.Struct" 或 "Struct") - * @param fieldName 字段名 - * @return 槽位下标;若未知返回 null - */ - public Integer lookupFieldIndex(String structName, String fieldName) { - // 先按原样查 - Map layout = STRUCT_LAYOUTS.get(structName); - // 兼容 “模块.结构体” 的写法:若没命中,退化为简单名再查 - if (layout == null && structName != null) { - int dot = structName.lastIndexOf('.'); - if (dot >= 0 && dot + 1 < structName.length()) { - layout = STRUCT_LAYOUTS.get(structName.substring(dot + 1)); - } - } - if (layout == null) return null; - return layout.get(fieldName); - } - } -- Gitee From 205dac01aeeed39dfbdd9a9eb40d9f7efc220e12 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 17:22:59 +0800 Subject: [PATCH 13/19] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=88=90?= =?UTF-8?q?=E5=91=98=E8=AE=BF=E9=97=AE=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了成员访问表达式的处理流程,提高了代码可读性和可维护性 - 增加了对结构体继承和字段去重的处理,解决了父类字段下标重复计算的问题 - 改进了模块常量加载的逻辑,简化了代码结构 - 重新组织了代码结构,增加了注释,提高了代码的可理解性 --- .../ir/builder/handlers/MemberHandler.java | 153 ++++++++++++++---- 1 file changed, 124 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/MemberHandler.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/MemberHandler.java index f582002b..f39f7923 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/MemberHandler.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/handlers/MemberHandler.java @@ -1,5 +1,6 @@ package org.jcnc.snow.compiler.ir.builder.handlers; +import org.jcnc.snow.compiler.ir.builder.core.IRBuilderScope; import org.jcnc.snow.compiler.ir.builder.expression.ExpressionBuilder; import org.jcnc.snow.compiler.ir.builder.expression.ExpressionHandler; import org.jcnc.snow.compiler.ir.common.GlobalConstTable; @@ -11,64 +12,70 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.parser.ast.IdentifierNode; import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** - * 成员访问(MemberExpressionNode)处理器。 + * {@code MemberHandler} 是成员访问表达式的处理器, + * 负责将 obj.field 类型的成员访问降级为底层的 __index_r(obj, fieldIndex) 调用。 + * 主要解决结构体继承层级下 fieldIndex 的正确计算,避免父类字段下标重复累计的问题。 *

                                                      - * 负责处理对象字段、静态常量、模块常量等成员访问表达式,自动分派到对应的 IR 指令。 - * 支持对模块常量的优化直接折叠,也支持动态对象字段读取。 + * 功能概述: + *

                                                        + *
                                                      • 对普通对象成员访问(如 obj.field)进行翻译,将其转换为 IR 的 __index_r(obj, fieldIndex) 形式;
                                                      • + *
                                                      • 处理模块常量(如 ModuleName.constName),直接生成常量加载指令;
                                                      • + *
                                                      • 智能处理扁平化与未扁平化结构体布局,准确计算字段的全局下标,兼容继承链与字段去重。
                                                      • + *
                                                      */ public class MemberHandler implements ExpressionHandler { + /** - * 处理成员访问表达式,返回对应的虚拟寄存器。 + * 处理成员访问表达式,将 obj.field 转换为 __index_r(obj, fieldIndex) IR 表达式。 + * 如果是 ModuleName.constName 这样的模块级常量,直接生成常量加载。 * * @param b 表达式构建器 - * @param mem 成员访问 AST 节点 - * @return 存放成员值的虚拟寄存器 + * @param mem 成员访问表达式 AST 节点 + * @return IR 虚拟寄存器,存放成员访问结果 */ @Override public IRVirtualRegister handle(ExpressionBuilder b, MemberExpressionNode mem) { - // ===== 1. 优先判定为模块常量(形如 mod.CONST)===== - if (mem.object() instanceof IdentifierNode oid) { - String mod = oid.name(); - Object c = GlobalConstTable.get(mod + "." + mem.member()); - if (c != null) { - // 命中全局常量表,直接生成常量加载指令 - IRVirtualRegister r = b.ctx().newRegister(); - b.ctx().addInstruction(new LoadConstInstruction(r, new IRConstant(c))); - return r; + // 特殊分支:如果是 ModuleName.constName,直接从全局常量表取常量 + if (mem.object() instanceof IdentifierNode modId) { + Object constVal = GlobalConstTable.get(modId.name() + "." + mem.member()); + if (constVal != null) { + IRVirtualRegister outConst = b.ctx().newRegister(); + b.ctx().addInstruction(new LoadConstInstruction(outConst, IRConstant.fromObject(constVal))); + return outConst; } } - // ===== 2. 常规对象字段访问(如 obj.field)===== - IRVirtualRegister objReg = b.build(mem.object()); // 先获取对象寄存器 + // 1. 计算被访问对象的寄存器 + IRVirtualRegister objReg = b.build(mem.object()); - // ===== 3. 推断 owner 类型(优先用 object 的类型,否则 fallback 到 this 的类型)===== + // 2. 解析对象的类型(优先使用标识符,否则尝试 this) String ownerType = null; - if (mem.object() instanceof IdentifierNode oid) { - ownerType = b.ctx().getScope().lookupType(oid.name()); + if (mem.object() instanceof IdentifierNode id) { + ownerType = b.ctx().getScope().lookupType(id.name()); } if (ownerType == null || ownerType.isEmpty()) { - // 若找不到 object 的类型,则尝试 this String thisType = b.ctx().getScope().lookupType("this"); - if (thisType != null) ownerType = thisType; + if (thisType != null && !thisType.isEmpty()) { + ownerType = thisType; + } } if (ownerType == null || ownerType.isEmpty()) { throw new IllegalStateException("无法解析成员访问接收者的类型"); } - // ===== 4. 查询字段索引(field offset),找不到直接报错 ===== - Integer fieldIndex = b.ctx().getScope().lookupFieldIndex(ownerType, mem.member()); + // 3. 计算字段下标 + Integer fieldIndex = resolveFieldIndex(ownerType, mem.member()); if (fieldIndex == null) { throw new IllegalStateException("类型 " + ownerType + " 不存在字段: " + mem.member()); } - // ===== 5. 生成下标参数,转为 __index_r 统一成员取值指令 ===== + // 4. 生成 __index_r(obj, idx) 指令 IRVirtualRegister idxReg = b.ctx().newRegister(); - b.ctx().addInstruction(new LoadConstInstruction(idxReg, - IRConstant.fromNumber(Integer.toString(fieldIndex)))); + b.ctx().addInstruction(new LoadConstInstruction( + idxReg, IRConstant.fromNumber(Integer.toString(fieldIndex)))); IRVirtualRegister out = b.ctx().newRegister(); List args = new ArrayList<>(); @@ -77,4 +84,92 @@ public class MemberHandler implements ExpressionHandler { b.ctx().addInstruction(new CallInstruction(out, "__index_r", args)); return out; } + + /** + * 计算结构体字段的下标槽位。 + *
                                                        + *
                                                      • 若子类布局已扁平化(包含父类字段),直接返回布局中的下标;
                                                      • + *
                                                      • 若未扁平化,则下标 = 去重累计的祖先字段数量 + 自身布局下标;
                                                      • + *
                                                      • 若字段声明于祖先类,递归上溯继承链,并累计去重的祖先字段数量;
                                                      • + *
                                                      + * + * @param structName 结构体名 + * @param fieldName 字段名 + * @return 字段在对象布局中的下标,找不到时返回 null + */ + private Integer resolveFieldIndex(String structName, String fieldName) { + Map selfLayout = IRBuilderScope.getStructLayout(structName); + + // 情况 A:字段在本类声明 + if (selfLayout != null && selfLayout.containsKey(fieldName)) { + if (isFlattenedWithParent(structName, selfLayout)) { + // 已扁平化:布局里的下标就是全局槽位 + return selfLayout.get(fieldName); + } else { + // 未扁平化:加上“去重后的祖先字段数” + return countDistinctAncestorFields(structName) + selfLayout.get(fieldName); + } + } + + // 情况 B:字段在祖先类声明 —— 去重累计祖先字段数 + int offset = 0; + Set seen = new HashSet<>(); + String anc = IRBuilderScope.getStructParent(structName); + while (anc != null) { + Map ancLayout = IRBuilderScope.getStructLayout(anc); + if (ancLayout != null) { + if (ancLayout.containsKey(fieldName)) { + // 找到声明处:offset + 祖先布局中的下标 + return offset + ancLayout.get(fieldName); + } + // 累计去重后的字段数 + for (String k : ancLayout.keySet()) { + if (seen.add(k)) { + offset++; + } + } + } + anc = IRBuilderScope.getStructParent(anc); + } + return null; + } + + /** + * 判断结构体布局是否已经“扁平化”地包含父类字段。 + * 若任意父类字段出现在子类布局中,则认为已经扁平化。 + * + * @param structName 当前结构体名 + * @param childLayout 当前结构体的字段布局 + * @return 如果已扁平化,返回 true;否则 false + */ + private boolean isFlattenedWithParent(String structName, Map childLayout) { + String parent = IRBuilderScope.getStructParent(structName); + if (parent == null) return true; + Map parentLayout = IRBuilderScope.getStructLayout(parent); + if (parentLayout == null || parentLayout.isEmpty()) return true; + for (String k : parentLayout.keySet()) { + if (childLayout.containsKey(k)) return true; + } + return false; + } + + /** + * 统计所有祖先类字段的数量(去重), + * 用于未扁平化继承场景,防止字段下标因继承链重复计算。 + * + * @param structName 当前结构体名 + * @return 所有祖先类字段(去重后)的总数 + */ + private int countDistinctAncestorFields(String structName) { + Set seen = new HashSet<>(); + String anc = IRBuilderScope.getStructParent(structName); + while (anc != null) { + Map ancLayout = IRBuilderScope.getStructLayout(anc); + if (ancLayout != null) { + seen.addAll(ancLayout.keySet()); + } + anc = IRBuilderScope.getStructParent(anc); + } + return seen.size(); + } } -- Gitee From c352fcdee9a78ab756fb8cb2040893948c1298fe Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 17:40:21 +0800 Subject: [PATCH 14/19] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=20Graduate=20?= =?UTF-8?q?=E7=B1=BB=E5=B9=B6=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Graduate 类,继承自 Student 类 - 在 Main.snow 中创建 Graduate 对象并调用 getName 方法 - 优化 Person 和 Student 类的代码格式 --- playground/Demo/Demo34/Graduate.snow | 22 +++++++++++++++++ playground/Demo/Demo34/Main.snow | 7 +++--- playground/Demo/Demo34/Person.snow | 34 +++++++++++++------------- playground/Demo/Demo34/Student.snow | 36 +++++++++++++--------------- 4 files changed, 58 insertions(+), 41 deletions(-) create mode 100644 playground/Demo/Demo34/Graduate.snow diff --git a/playground/Demo/Demo34/Graduate.snow b/playground/Demo/Demo34/Graduate.snow new file mode 100644 index 00000000..50d7e761 --- /dev/null +++ b/playground/Demo/Demo34/Graduate.snow @@ -0,0 +1,22 @@ +module: Graduate + import: Student + struct: Graduate extends Student + fields: + declare year: int + init: + params: + declare name: int + declare year: int + body: + super(name) + this.year = year + end body + end init + function: getName + returns: int + body: + return super.getName() + this.year + end body + end function + end struct +end module diff --git a/playground/Demo/Demo34/Main.snow b/playground/Demo/Demo34/Main.snow index d681d77c..5be9389d 100644 --- a/playground/Demo/Demo34/Main.snow +++ b/playground/Demo/Demo34/Main.snow @@ -1,14 +1,13 @@ module: main - import: os,Student, Person + import: os,Student, Person, Graduate function: main returns: void body: declare a: Person = new Student(1) - os.println(a.getName()) - - + declare p: Person = new Graduate(10, 2024) + os.println(p.getName()) end body end function end module \ No newline at end of file diff --git a/playground/Demo/Demo34/Person.snow b/playground/Demo/Demo34/Person.snow index 395cd06a..868ee4fa 100644 --- a/playground/Demo/Demo34/Person.snow +++ b/playground/Demo/Demo34/Person.snow @@ -1,20 +1,20 @@ module: Person -struct:Person - fields: - declare name: int - init: - params: - declare name: int - body: - this.name = name - end body - end init + struct:Person + fields: + declare name: int + init: + params: + declare name: int + body: + this.name = name + end body + end init - function: getName - returns: int - body: - return this.name - end body - end function -end struct + function: getName + returns: int + body: + return this.name + end body + end function + end struct end module \ No newline at end of file diff --git a/playground/Demo/Demo34/Student.snow b/playground/Demo/Demo34/Student.snow index a1cf41a4..3c750927 100644 --- a/playground/Demo/Demo34/Student.snow +++ b/playground/Demo/Demo34/Student.snow @@ -1,24 +1,20 @@ module: Student -import : Person + import : Person -struct : Student extends Person - fields: - declare id: int + struct : Student extends Person + init: + params: + declare name: int + body: + super(name) + end body + end init - init: - params: - declare name: int - body: - super(name) - end body - end init - - // 重写父类方法,演示多态 - function: getName - returns: int - body: - return super.getName() + 1000 - end body - end function -end struct + function: getName + returns: int + body: + return super.getName() + 1000 + end body + end function + end struct end module -- Gitee From dfc30a7c2b400db0ea107da9d788342efdb0bb48 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 10 Sep 2025 17:59:41 +0800 Subject: [PATCH 15/19] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=20Demo34=20?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E9=85=8D=E7=BD=AE=E4=B8=AD=E7=9A=84=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/Demo34.run.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.run/Demo34.run.xml b/.run/Demo34.run.xml index d6e74c28..050c8705 100644 --- a/.run/Demo34.run.xml +++ b/.run/Demo34.run.xml @@ -2,7 +2,7 @@