Skip to content

Commit 67b4685

Browse files
committed
优化循环
类的gc机制
1 parent 60fef54 commit 67b4685

File tree

10 files changed

+91
-53
lines changed

10 files changed

+91
-53
lines changed

src/main/kotlin/top/mcfpp/Project.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.antlr.v4.runtime.tree.ParseTree
88
import org.apache.logging.log4j.LogManager
99
import org.apache.logging.log4j.Logger
1010
import top.mcfpp.annotations.InsertCommand
11+
import top.mcfpp.command.Command
1112
import top.mcfpp.command.Commands
1213
import top.mcfpp.command.CommentLevel
1314
import top.mcfpp.core.lang.ClassPointer
@@ -17,6 +18,7 @@ import top.mcfpp.core.lang.Var
1718
import top.mcfpp.io.LibReader
1819
import top.mcfpp.io.LibWriter
1920
import top.mcfpp.io.MCFPPFile
21+
import top.mcfpp.lib.SbObject
2022
import top.mcfpp.model.Native
2123
import top.mcfpp.model.ObjectClass
2224
import top.mcfpp.model.field.GlobalField
@@ -72,6 +74,18 @@ object Project {
7274

7375
lateinit var mcfppInit : Function
7476

77+
val mcfppSystemTick: Function = Function("sys.tick","mcfpp", null).apply {
78+
commands.addAll(
79+
arrayOf(
80+
//指针清理
81+
Command("execute as @e[type=marker,tag=mcfpp_ptr] if score @s ${SbObject.MCFPP_POINTER_COUNTER} matches ..0 run kill @s"),
82+
//内存泄露检查
83+
Command("execute if data storage mcfpp:system stack_frame[0] run tellraw @a {\"text\":\"[MCFPP]Stack Leak\"}"),
84+
Command("execute if data storage mcfpp:system stack_frame[0] run data modify storage mcfpp:system stack_frame set value []"),
85+
)
86+
)
87+
}
88+
7589
/**
7690
* 常量池
7791
*/

src/main/kotlin/top/mcfpp/antlr/MCFPPExprVisitor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ class MCFPPExprVisitor(private var defaultGenericClassType : MCFPPGenericClassTy
459459
} else {
460460
constructor.invoke(normalArgs, ptr)
461461
}
462+
ptr.isNull = false
462463
return ptr
463464
}
464465
//可能是模板的构造函数

src/main/kotlin/top/mcfpp/antlr/MCFPPImVisitor.kt

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
7373
if(Function.currFunction !is Generic<*> && Function.currFunction.returnType != MCFPPBaseType.Void && !Function.currFunction.hasReturnStatement){
7474
LogProcessor.error("Function should return a value: " + Function.currFunction.namespaceID)
7575
}
76+
//释放指针
77+
Function.currFunction.disposeClassPtr()
7678
Function.currFunction = Function.nullFunction
7779
if (Class.currClass == null) {
7880
//不在类中
@@ -305,6 +307,8 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
305307
if (Function.currFunction.returnType != MCFPPBaseType.Void && !Function.currFunction.hasReturnStatement) {
306308
LogProcessor.error("A 'return' expression required in function: " + Function.currFunction.namespaceID)
307309
}
310+
//释放指针
311+
Function.currFunction.disposeClassPtr()
308312
Function.currFunction = Function.nullFunction
309313
}
310314

@@ -565,8 +569,10 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
565569
//进入if函数
566570
Project.ctx = ctx
567571
Function.addComment("while start")
572+
//外while函数。这个函数中包含了while循环的逻辑
568573
val whileFunction = InternalFunction("_while_", Function.currFunction)
569-
Function.addCommand("function " + whileFunction.namespaceID)
574+
Function.addCommand(Commands.stackIn())
575+
Function.addCommand(Commands.function(whileFunction))
570576
Function.addCommand(Commands.stackOut())
571577
Function.currFunction = whileFunction
572578
if(!GlobalField.localNamespaces.containsKey(whileFunction.namespace))
@@ -603,20 +609,18 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
603609
Function.addCommand(Commands.stackIn())
604610
Function.addComment("while start")
605611
val parent: mcfppParser.WhileStatementContext = ctx.parent as mcfppParser.WhileStatementContext
606-
val exp = MCFPPExprVisitor().visitExpression(parent.expression())
607-
//匿名函数的定义
612+
//while语句块编译的目标函数,即内while函数
608613
val f: Function = InternalFunction("_while_block_", Function.currFunction)
609614
f.child.add(f)
610615
f.parent.add(f)
611616
if(!GlobalField.localNamespaces.containsKey(f.namespace))
612617
GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
613618
GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f,false)
614-
//条件判断
615-
when(exp){
619+
//循环条件判断,此时目标函数是外while函数。条件表达式在外while中计算。
620+
when(val exp = MCFPPExprVisitor().visitExpression(parent.expression())){
616621
is ScoreBoolConcrete -> {
617622
if(exp.value){
618-
//给子函数开栈
619-
Function.addCommand(Commands.stackIn())
623+
//内while函数的返回值表示循环是否被阻断,使用execute if判断。若成立,则继续运行外while函数
620624
Function.addCommand("execute " +
621625
"if function " + f.namespaceID + " " +
622626
"run function " + Function.currFunction.namespaceID)
@@ -626,17 +630,13 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
626630
}
627631

628632
is ExecuteBool -> {
629-
//给子函数开栈
630-
Function.addCommand(Commands.stackIn())
631633
Function.addCommand(Command("execute")
632634
.build(exp.toCommandPart())
633635
.build("if function " + f.namespaceID)
634636
.build("run function " + Function.currFunction.namespaceID))
635637
}
636638

637639
is BaseBool -> {
638-
//给子函数开栈
639-
Function.addCommand(Commands.stackIn())
640640
Function.addCommand(Command("execute")
641641
.build("if").build(exp.toCommandPart())
642642
.build("if function " + f.namespaceID)
@@ -661,17 +661,13 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
661661
@InsertCommand
662662
fun exitWhileBlock(ctx: mcfppParser.WhileBlockContext) {
663663
Project.ctx = ctx
664-
//调用完毕,将子函数的栈销毁
665-
//由于在同一个命令中完成了两个函数的调用,因此需要在子函数内部进行子函数栈的销毁工作
666-
Function.addCommand(Commands.stackOut())
667-
//这里取出while函数的栈
668-
Function.addCommand(Commands.stackOut())
664+
Function.currFunction.disposeClassPtr()
669665
Function.addCommand("return 1")
670666
Function.currFunction = Function.currFunction.parent[0]
671667
Function.addComment("while loop end")
672668
Function.currFunction.field.forEachVar {
673-
if(it.trackLost){
674-
it.trackLost = false
669+
if(!it.trackLost){
670+
it.trackLost = true
675671
if(it is MCFPPValue<*>) it.toDynamic(true)
676672
}
677673
}
@@ -691,6 +687,10 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
691687
Project.ctx = ctx
692688
Function.addComment("do-while start")
693689
doWhileFunction = InternalFunction("_dowhile_", Function.currFunction)
690+
//这里不能急着调用循环函数,因为循环体必定会执行一次。参见enterDoWhileBlock的代码
691+
//Function.addCommand(Commands.stackIn())
692+
//Function.addCommand(Commands.function(doWhileFunction))
693+
//Function.addCommand(Commands.stackOut())
694694
Function.currFunction = doWhileFunction
695695
if(!GlobalField.localNamespaces.containsKey(doWhileFunction.namespace))
696696
GlobalField.localNamespaces[doWhileFunction.namespace] = Namespace(doWhileFunction.namespace)
@@ -738,19 +738,23 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
738738
}
739739
GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f,false)
740740
//给子函数开栈
741-
Function.currFunction.parent[0].commands.add(Commands.stackIn())
742-
Function.currFunction.parent[0].commands.add("execute unless function ${f.namespaceID} run return 1")
743-
Function.currFunction.parent[0].commands.add(Commands.stackOut())
744-
Function.currFunction.parent[0].commands.add(Commands.stackIn())
745-
Function.currFunction.parent[0].commands.add("function " + doWhileFunction.namespaceID)
746-
Function.currFunction.parent[0].commands.add(Commands.stackOut())
741+
Function.currFunction.parent[0].commands.addAll(
742+
arrayOf(
743+
//必然调用一次循环体内的函数
744+
Commands.stackIn(),
745+
Commands.function(f),
746+
Commands.stackOut(),
747+
//然后才开始调用do-while外函数。此时就是先判断再执行,转换为了while语句
748+
Commands.stackIn(),
749+
Commands.function(doWhileFunction),
750+
Commands.stackOut()
751+
)
752+
)
747753
//递归调用
748754
val parent = ctx.parent as mcfppParser.DoWhileStatementContext
749755
when(val exp = MCFPPExprVisitor().visitExpression(parent.expression())){
750756
is ScoreBoolConcrete -> {
751757
if(exp.value){
752-
//给子函数开栈
753-
Function.addCommand(Commands.stackIn())
754758
Function.addCommand("execute " +
755759
"if function " + f.namespaceID + " " +
756760
"run function " + Function.currFunction.namespaceID)
@@ -762,17 +766,13 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
762766
}
763767

764768
is ExecuteBool -> {
765-
//给子函数开栈
766-
Function.addCommand(Commands.stackIn())
767769
Function.addCommand(Command("execute")
768770
.build(exp.toCommandPart())
769771
.build("if function " + f.namespaceID)
770772
.build("run function " + Function.currFunction.namespaceID))
771773
}
772774

773775
is BaseBool -> {
774-
//给子函数开栈
775-
Function.addCommand(Commands.stackIn())
776776
Function.addCommand(Command("execute")
777777
.build("if").build(exp.toCommandPart())
778778
.build("if function " + f.namespaceID)
@@ -792,8 +792,7 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
792792
@InsertCommand
793793
fun exitDoWhileBlock(ctx: mcfppParser.DoWhileBlockContext) {
794794
Project.ctx = ctx
795-
//调用完毕,将子函数的栈销毁
796-
Function.addCommand(Commands.stackOut())
795+
Function.currFunction.disposeClassPtr()
797796
//返回1
798797
Function.addCommand("return 1")
799798
Function.currFunction = Function.currFunction.parent[0]

src/main/kotlin/top/mcfpp/core/lang/ClassPointer.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ open class ClassPointer : Var<ClassPointer>{
7474
constructor(classPointer: ClassPointer) : super(classPointer) {
7575
type = classPointer.type
7676
instanceField = classPointer.instanceField
77+
isNull = classPointer.isNull
7778
}
7879

7980
/**
@@ -140,9 +141,10 @@ open class ClassPointer : Var<ClassPointer>{
140141
fun dispose(){
141142
if (!isNull) {
142143
//原实体中的实例减少一个指针
143-
val c = Commands.selectRun(this,Commands.sbPlayerRemove(MCInt("@s").setObj(SbObject.MCFPP_POINTER_COUNTER) as MCInt, 1))
144+
val c = Commands.selectRun(this, Commands.sbPlayerRemove(MCInt("@s").setObj(SbObject.MCFPP_POINTER_COUNTER) as MCInt, 1))
144145
Function.addCommands(c)
145146
}
147+
isNull = true
146148
}
147149

148150
@Override

src/main/kotlin/top/mcfpp/lib/NBTPath.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class NBTPath(var source: NBTSource): Serializable {
164164

165165
val temp = NBTPath(StorageSource("mcfpp:system")).memberIndex("temp")
166166

167+
val stack = NBTPath(StorageSource("mcfpp:system")).memberIndex("stack_frame")
168+
167169
val STORAGE = "storage"
168170
val ENTITY = "entity"
169171
val BLOCK = "block"
@@ -218,9 +220,6 @@ class NBTPath(var source: NBTSource): Serializable {
218220
.memberIndex("stack_frame[${v.stackIndex}]")
219221
.memberIndex(v.identifier)
220222
}
221-
222-
fun getNormalStackPath(stackIndex: Int = 0)
223-
= NBTPath(StorageSource("mcfpp:system")).memberIndex("stack_frame[$stackIndex]")
224223
}
225224

226225
}

src/main/kotlin/top/mcfpp/model/field/FunctionField.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package top.mcfpp.model.field
22

33
import org.jetbrains.annotations.Nullable
44
import top.mcfpp.core.lang.Var
5-
import top.mcfpp.type.MCFPPType
65
import top.mcfpp.model.FieldContainer
7-
import kotlin.collections.HashMap
8-
import kotlin.collections.HashSet
6+
import top.mcfpp.type.MCFPPType
97

108
/**
119
* 一个函数的域。储存了这个函数中的变量

src/main/kotlin/top/mcfpp/model/field/GlobalField.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,12 @@ object GlobalField : FieldContainer, IField {
9090
stdNamespaces["mcfpp"]!!.field.addFunction(Project.mcfppLoad,true)
9191
stdNamespaces["mcfpp"]!!.field.addFunction(Project.mcfppTick,true)
9292
stdNamespaces["mcfpp"]!!.field.addFunction(Project.mcfppInit, true)
93+
stdNamespaces["mcfpp"]!!.field.addFunction(Project.mcfppSystemTick, true)
9394

94-
functionTags["minecraft:tick"]!!.functions.add(Project.mcfppTick)
95-
functionTags["minecraft:load"]!!.functions.add(Project.mcfppLoad)
96-
functionTags["minecraft:load"]!!.functions.add(Project.mcfppInit)
95+
FunctionTag.TICK.functions.add(Project.mcfppTick)
96+
FunctionTag.TICK.functions.add(Project.mcfppSystemTick)
97+
FunctionTag.LOAD.functions.add(Project.mcfppLoad)
98+
FunctionTag.LOAD.functions.add(Project.mcfppInit)
9799

98100
stdNamespaces["mcfpp.lang"]!!.field.addTemplate("DataObject", DataTemplate.baseDataTemplate)
99101
DataTemplate.baseDataTemplate.getNativeFromClass(DataObjectData::class.java)

src/main/kotlin/top/mcfpp/model/function/ClassConstructor.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ open class ClassConstructor
4040
funcs.append("}")
4141
//对象实体创建
4242
if(target.baseEntity == Class.ENTITY_MARKER){
43-
addCommand("data merge entity @s {Tags:[${target.tag},${target.tag}_data,just],data:{$funcs}}")
43+
addCommand("data merge entity @s {Tags:[${target.tag},${target.tag}_data,mcfpp_ptr,just],data:{$funcs}}")
4444
}else if(target.baseEntity == Class.ENTITY_ITEM_DISPLAY){
45-
addCommand("data modify entity @s item.components.\"minecraft:custom_data\".mcfppData set value {Tags:[${target.tag},${target.tag}_data,just],data:{$funcs}}")
45+
addCommand("data modify entity @s item.components.\"minecraft:custom_data\".mcfppData set value {Tags:[${target.tag},${target.tag}_data,mcfpp_ptr,just],data:{$funcs}}")
4646
}else{
4747
addCommand("tag @s add ${target.tag}")
48-
addCommand("execute summon marker run data merge entity @s {Tags:[${target.tag}_data,just],data:{$funcs}}")
48+
addCommand("summon marker ~ ~ ~ {Tags:[${target.tag}_data,mcfpp_ptr,just],data:{$funcs}}")
4949
addCommand("ride @n[tag=just, type=marker] mount @s")
5050
addCommand("tag @n[tag=just, type=marker] remove just")
5151
}

src/main/kotlin/top/mcfpp/model/function/Function.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,14 @@ open class Function : Member, FieldContainer, Serializable, WithDocument {
905905
currFunction = old
906906
}
907907

908+
fun disposeClassPtr(){
909+
for (p in field.allVars){
910+
if (p is ClassPointer){
911+
p.dispose()
912+
}
913+
}
914+
}
915+
908916
companion object {
909917
/**
910918
* 用于处理多余的命令的函数
@@ -937,6 +945,7 @@ open class Function : Member, FieldContainer, Serializable, WithDocument {
937945
return ret
938946
}
939947

948+
940949
@Suppress("unused")
941950
fun replaceCommand(command: String, index: Int){
942951
replaceCommand(Command(command),index)

test/test.mcfpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
namespace test;
22

3+
34
func main(){
4-
solveHanoi(3, 1, 3, 2);
5+
Test t1 = Test();
6+
Test t2 = Test();
7+
print(t1.getId());
8+
print(t2.getId());
9+
print(Test.s_id);
510
}
611

7-
func solveHanoi(int n, int f, int to, int aux) {
8-
if(n == 1) {
9-
print("Move disk 1 from rod " + f.toText() + " to rod " + to.toText());
10-
return;
12+
class Test{
13+
14+
int id;
15+
16+
constructor(){
17+
this.id = Test.s_id;
18+
Test.s_id = Test.s_id + 1;
19+
}
20+
21+
public func getId() -> int{
22+
return this.id;
1123
}
12-
solveHanoi(n-1, f, aux, to);
13-
print("Move disk " + n.toText() + " from rod " + f.toText() + " to rod " + to.toText());
14-
solveHanoi(n-1, aux, to, f);
24+
25+
}
26+
27+
object class Test{
28+
int s_id = 0;
1529
}

0 commit comments

Comments
 (0)