() {
- /**
- * 遍历整个文件。一个文件包含了命名空间的声明,函数的声明,类的声明以及全局变量的声明。全局变量是可以跨文件调用的。
- *
- * `
- * compilationUnit
- * : namespaceDeclaration?
- * typeDeclaration *
- * EOF
- * ;
- ` *
-
*
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitCompilationUnit(ctx: mcfppParser.CompilationUnitContext): Any? {
- //命名空间
- if (ctx.namespaceDeclaration() != null) {
- Project.currNamespace = ctx.namespaceDeclaration()!!.Identifier().text
- }
- //文件结构,类和函数
- for (t in ctx.typeDeclaration()) {
- visit(t)
- }
- return null
- }
-
- /**
- * 类或者函数的声明
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitTypeDeclaration(ctx: mcfppParser.TypeDeclarationContext): Any? {
- visit(ctx.classOrFunctionDeclaration())
- return null
- }
-
- /**
- * 类或函数声明
- *
- * `classOrFunctionDeclaration
- * : classDeclaration
- * | functionDeclaration
- * | nativeDeclaration
- * ;`
-
*
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitClassOrFunctionDeclaration(ctx: mcfppParser.ClassOrFunctionDeclarationContext): Any? {
- if (ctx.classDeclaration() != null) {
- visit(ctx.classDeclaration())
- } else if (ctx.functionDeclaration() != null) {
- visit(ctx.functionDeclaration())
- } else if (ctx.nativeFuncDeclaration() != null) {
- visit(ctx.nativeFuncDeclaration())
- } else {
- visit(ctx.nativeClassDeclaration())
- }
- return null
- }
-
- /**
- * native类的声明
- * @param ctx the parse tree
- * @return null
- */
- override fun visitNativeClassDeclaration(ctx: mcfppParser.NativeClassDeclarationContext): Any? {
- //注册类
- val identifier: String = ctx.className().text
- return if (Project.global.cache.classes.containsKey(identifier)) {
- //重复声明
- Project.logger.error(
- "The class has extended " + Class.currClass!!.identifier +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- throw ClassDuplicationException()
- } else {
- //获取它指向的java类
- val cls: java.lang.Class = try {
- java.lang.Class.forName(ctx.javaRefer().text) as java.lang.Class
- } catch (e: ClassNotFoundException) {
- throw RuntimeException(e)
- } catch (e: ClassCastException) {
- throw RuntimeException(e)
- }
- val ncls: NativeClass = if (ctx.className().Identifier() != null) {
- //声明了命名空间
- NativeClass(identifier, ctx.className().Identifier().text, cls)
- } else {
- NativeClass(identifier, cls)
- }
- Project.global.cache.classes[identifier] = ncls
- null
- }
- }
-
- /**
- * 类的声明
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitClassDeclaration(ctx: mcfppParser.ClassDeclarationContext): Any? {
- //注册类
- val identifier: String = ctx.className(0).text
- if (Project.global.cache.classes.containsKey(identifier)) {
- //重复声明
- Project.logger.error(
- "The class has extended " + Class.currClass!!.identifier +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- throw ClassDuplicationException()
- } else {
- //如果没有声明过这个类
- val cls: Class = if (ctx.className(0).Identifier() != null) {
- //声明了命名空间
- Class(identifier, ctx.className(0).Identifier().text)
- } else {
- Class(identifier)
- }
- if (ctx.className().size != 1) {
- if (Project.global.cache.classes.containsKey(ctx.className(1).text)) {
- cls.parent = Project.global.cache.classes[ctx.className(1).text]
- } else {
- Project.logger.error(
- "Undefined class: " + ctx.className(1).text +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- }
- }
- Project.global.cache.classes[identifier] = cls
- Class.currClass = cls
- cls.isStaticClass = ctx.STATIC() != null
- }
- //解析类中的成员
- //先静态
- //先解析函数
- for (c in ctx.classBody().staticClassMemberDeclaration()) {
- if (c!!.classMember().fieldDeclaration() == null) {
- visit(c)
- }
- }
- //再解析变量
- for (c in ctx.classBody().staticClassMemberDeclaration()) {
- if (c!!.classMember().fieldDeclaration() != null) {
- visit(c)
- }
- }
- //后成员
- //先解析函数和构造函数
- for (c in ctx.classBody().classMemberDeclaration()) {
- if (c!!.classMember().fieldDeclaration() == null) {
- visit(c)
- }
- }
- //再解析变量
- for (c in ctx.classBody().classMemberDeclaration()) {
- if (c!!.classMember().fieldDeclaration() != null) {
- visit(c)
- }
- }
- //如果没有构造函数,自动添加默认的空构造函数
- if (Class.currClass!!.constructors.size == 0) {
- Class.currClass!!.addConstructor(Constructor(Class.currClass!!))
- }
- Class.currClass = null
- return null
- }
-
- @Override
- override fun visitStaticClassMemberDeclaration(ctx: mcfppParser.StaticClassMemberDeclarationContext): Any? {
- val m = visit(ctx.classMember()) as ClassMember
- //访问修饰符
- if (ctx.accessModifier() != null) {
- m.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
- }
- m.isStatic = true
- Class.currClass!!.addMember(m)
- return null
- }
-
- /**
- * 类成员的声明。由于函数声明可以后置,因此需要先查明函数声明情况再进行变量的注册以及初始化。
- *
- * `classMemberDeclaration
- * : accessModifier? (STATIC)? classMember
- * ;
- `
*
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitClassMemberDeclaration(ctx: mcfppParser.ClassMemberDeclarationContext): Any? {
- val m = visit(ctx.classMember()) as ClassMember
- //访问修饰符
- if (ctx.accessModifier() != null) {
- m.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
- }
- if (m !is Constructor) {
- Class.currClass!!.addMember(m)
- }
- return null
- }
-
- @Override
- override fun visitClassMember(ctx: mcfppParser.ClassMemberContext): Any? {
- return if (ctx.nativeFuncDeclaration() != null) {
- visit(ctx.nativeFuncDeclaration())
- } else if (ctx.classFunctionDeclaration() != null) {
- visit(ctx.classFunctionDeclaration())
- } else if (ctx.fieldDeclaration() != null) {
- visit(ctx.fieldDeclaration())
- } else if (ctx.constructorDeclaration() != null) {
- visit(ctx.constructorDeclaration())
- } else {
- visit(ctx.nativeConstructorDeclaration())
- }
- }
-
- /**
- * 类方法的声明
- * @param ctx the parse tree
- * @return 这个类方法的对象
- */
- @Override
- override fun visitClassFunctionDeclaration(ctx: mcfppParser.ClassFunctionDeclarationContext): Any {
- //创建函数对象
- val f = Function(
- ctx.Identifier().text,
- Class.currClass!!,
- ctx.parent is mcfppParser.StaticClassMemberDeclarationContext
- )
- //解析参数
- if (ctx.parameterList() != null) {
- f.addParams(ctx.parameterList())
- }
- //注册函数
- if (Class.currClass!!.cache!!.functions.contains(f) || Class.currClass!!.staticCache!!.functions.contains(
- f
- )
- ) {
- Project.logger.error(
- "Already defined function:" + ctx.Identifier()
- .text + "in class " + Class.currClass!!.identifier +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- Function.currFunction = Function.nullFunction
- }
- return f
- }
-
- /**
- * 构造函数的声明
- * @param ctx the parse tree
- * @return 这个构造函数的对象
- */
- @Override
- override fun visitConstructorDeclaration(ctx: mcfppParser.ConstructorDeclarationContext): Any? {
- //是构造函数
- //创建构造函数对象,注册函数
- var f: Constructor? = null
- try {
- f = Constructor(Class.currClass!!)
- Class.currClass!!.addConstructor(f)
- } catch (e: FunctionDuplicationException) {
- Project.logger.error(
- "Already defined function: " + ctx.className().text + "(" + ctx.parameterList().text + ")" +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- }
- assert(f != null)
- if (ctx.parameterList() != null) {
- f!!.addParams(ctx.parameterList())
- }
- return f
- }
-
- @Override
- override fun visitNativeConstructorDeclaration(ctx: mcfppParser.NativeConstructorDeclarationContext?): Any? {
- //TODO
- throw TODOException("")
- }
-
- /**
- * 函数的声明
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitFunctionDeclaration(ctx: mcfppParser.FunctionDeclarationContext): Any? {
- //创建函数对象
- val f: Function
- //是否是内联函数
- //是否是内联函数
- if (ctx.INLINE() == null) {
- //获取函数的文本内容
- //函数是否拥有命名空间声明
- f = if (ctx.namespaceID().Identifier().size == 1) {
- InlineFunction(ctx.namespaceID().Identifier(0).text, ctx)
- } else {
- InlineFunction(
- ctx.namespaceID().Identifier(0).text,
- ctx.namespaceID().Identifier(1).text,
- ctx
- )
- }
- } else {
- //函数是否拥有命名空间声明
- f = if (ctx.namespaceID().Identifier().size == 1) {
- Function(ctx.namespaceID().Identifier(0).text)
- } else {
- Function(ctx.namespaceID().Identifier(0).text, ctx.namespaceID().Identifier(1).text)
- }
- }
- //解析参数
- if (ctx.parameterList() != null) {
- f.addParams(ctx.parameterList())
- }
- //解析函数的tag
- if (ctx.functionTag() != null) {
- val functionTag: FunctionTag = if (ctx.functionTag()!!.namespaceID().Identifier().size == 1) {
- FunctionTag(FunctionTag.MINECRAFT, ctx.functionTag()!!.namespaceID().Identifier(0).text)
- } else {
- FunctionTag(
- ctx.functionTag()!!.namespaceID().Identifier(0).text,
- ctx.functionTag()!!.namespaceID().Identifier(1).text
- )
- }
- if (Project.global.functionTags.containsKey(functionTag.namespaceID)) {
- f.tag = Project.global.functionTags[functionTag.namespaceID]
- } else {
- Project.global.functionTags[functionTag.namespaceID] = functionTag
- f.tag = functionTag
- }
- f.tag!!.cache.functions.add(f)
- }
- //不是类的成员
- f.isClassMember = false
- if (Project.global.cache.getFunction(f.namespace, f.name, f.paramTypeList) == null) {
- Project.global.cache.functions.add(f)
- } else {
- Project.logger.error(
- "Already defined function:" + f.namespaceID +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- Function.currFunction = Function.nullFunction
- }
- if (f.tag != null && (f.tag!! == FunctionTag.TICK || f.tag!! == FunctionTag.LOAD) && (ctx.parent as mcfppParser.FunctionDeclarationContext).parameterList()!!
- .parameter().size != 0
- ) {
- Project.logger.error(
- "Entrance function shouldn't have parameter:" + f.namespaceID +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- }
- return null
- }
-
- /**
- * native函数的声明
- * @param ctx the parse tree
- * @return 如果是全局,返回null,否则返回这个函数对象
- */
- @Override
- override fun visitNativeFuncDeclaration(ctx: mcfppParser.NativeFuncDeclarationContext): Any? {
- val nf: NativeFunction = try {
- NativeFunction(ctx.Identifier().text, ctx.javaRefer())
- } catch (e: IllegalFormatException) {
- Project.logger.error(
- "Illegal Java Method Name:" + e.message +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- return null
- } catch (e: ClassNotFoundException) {
- Project.logger.error(
- "Cannot find java class:" + e.message +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- return null
- } catch (e: NoSuchMethodException) {
- Project.logger.error(
- "No such method:" + e.message +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- return null
- }
- if (ctx.parameterList() != null) {
- nf.addParams(ctx.parameterList())
- }
- if (Class.currClass == null) {
- //是普通的函数
- nf.isClassMember = false
- if (!Project.global.cache.functions.contains(nf)) {
- Project.global.cache.functions.add(nf)
- } else {
- Project.logger.error(
- "Already defined function:" + ctx.Identifier().text +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- Function.currFunction = Function.nullFunction
- }
- return nf
- }
- //是类成员
- nf.isClassMember = true
- nf.parentClass = Class.currClass
- return nf
- }
-
- /**
- * 类字段的声明
- * @param ctx the parse tree
- * @return null
- */
- @Override
- override fun visitFieldDeclaration(ctx: mcfppParser.FieldDeclarationContext): Any {
- //变量生成
- val `var`: Var = Var.build(ctx, Class.currClass!!)!!
- //只有可能是类变量
- if (Class.currClass!!.cache!!.containVar(
- ctx.Identifier().text
- ) || Class.currClass!!.staticCache!!.containVar(ctx.Identifier().text)
- ) {
- Project.logger.error(
- "Duplicate defined variable name:" + ctx.Identifier().text +
- " at " + Project.currFile.name + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- throw VariableDuplicationException()
- }
- //变量的初始化
- if (ctx.expression() != null) {
- `var`.isConst = ConstStatus.ASSIGNED
- Function.currFunction = Class.currClass!!.classPreInit!!
- Function.addCommand("#" + ctx.text)
- val init: Var = McfppExprVisitor().visit(ctx.expression())!!
- try {
- `var`.assign(init)
- } catch (e: VariableConverseException) {
- Project.logger.error(
- "Cannot convert " + init.javaClass + " to " + `var`.javaClass +
- " at " + Class.currClass!!.identifier + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- Function.currFunction = Function.nullFunction
- throw VariableConverseException()
- }
- Function.currFunction = Function.nullFunction
- }
- return `var`
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/McfppFuncVisitor.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/McfppFuncVisitor.kt
deleted file mode 100644
index db9b6e5a..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/McfppFuncVisitor.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-import mcfppBaseVisitor
-import top.alumopper.mcfpp.Project
-
-/**
- * 获取函数用的visitor
- */
-class McfppFuncVisitor : mcfppBaseVisitor() {
- fun getFunction(ctx: mcfppParser.FunctionCallContext, args: ArrayList): Function? {
- return if (ctx.namespaceID() != null && ctx.basicExpression() == null) {
- val qwq: Function? = if (ctx.namespaceID().Identifier().size == 1) {
- Project.global.cache.getFunction(Project.currNamespace, ctx.namespaceID().Identifier(0).text, args)
- } else {
- Project.global.cache.getFunction(
- ctx.namespaceID().Identifier(0).text,
- ctx.namespaceID().Identifier(1).text,
- args
- )
- }
- qwq
- } else if (ctx.basicExpression() != null) {
- TODO()
- } else {
- TODO()
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/McfppImListener.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/McfppImListener.kt
deleted file mode 100644
index 90a57a53..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/McfppImListener.kt
+++ /dev/null
@@ -1,741 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-import mcfppBaseListener
-import org.antlr.v4.runtime.RuleContext
-import top.alumopper.mcfpp.Project
-import top.alumopper.mcfpp.command.Commands
-import top.alumopper.mcfpp.exception.*
-import top.alumopper.mcfpp.lang.*
-
-class McfppImListener : mcfppBaseListener() {
- /**
- * 进入一个函数体
- * @param ctx the parse tree
- */
- @Override
- override fun enterFunctionBody(ctx: mcfppParser.FunctionBodyContext) {
- var f: Function
- //获取函数对象
- if (ctx.parent.parent !is mcfppParser.ClassMemberContext) {
- //不是类成员
- //创建函数对象
- val parent: mcfppParser.FunctionDeclarationContext = ctx.parent as mcfppParser.FunctionDeclarationContext
- f = if (parent.namespaceID().Identifier().size == 1) {
- Function(parent.namespaceID().Identifier(0).text)
- } else {
- Function(
- parent.namespaceID().Identifier(0).text,
- parent.namespaceID().Identifier(1).text
- )
- }
- //解析参数
- if (parent.parameterList() != null) {
- f.addParams((ctx.parent as mcfppParser.FunctionDeclarationContext).parameterList())
- }
- //获取缓存中的对象
- f = Project.global.cache.getFunction(f.namespace, f.name, f.paramTypeList)!!
- } else if (ctx.parent is mcfppParser.ConstructorDeclarationContext) {
- //是构造函数
- //创建构造函数对象并解析参数
- val temp = Function("temp")
- if ((ctx.parent as mcfppParser.ConstructorDeclarationContext).parameterList() != null) {
- temp.addParams((ctx.parent as mcfppParser.ConstructorDeclarationContext).parameterList())
- }
- //获取缓存中的对象
- f = Class.currClass!!.getConstructor(FunctionParam.toStringList(temp.params))!!
- } else {
- //是类的成员函数
- //创建函数对象并解析参数
- val qwq: mcfppParser.ClassFunctionDeclarationContext = ctx.parent as mcfppParser.ClassFunctionDeclarationContext
- f = Function(qwq.Identifier().text, Class.currClass!!, false)
- if (qwq.parameterList() != null) {
- f.addParams(qwq.parameterList())
- }
- //获取缓存中的对象
- f = Class.currClass!!.cache!!.getFunction(f.namespace, f.name, f.paramTypeList)!!
- }
- Function.currFunction = f
- }
-
- /**
- * 离开一个函数体
- * @param ctx the parse tree
- */
- @Override
- override fun exitFunctionBody(ctx: mcfppParser.FunctionBodyContext?) {
- if (Class.currClass == null) {
- //不在类中
- Function.currFunction = Function.nullFunction
- } else {
- Function.currFunction = Class.currClass!!.classPreInit
- }
- }
-
- /**
- * 进入命名空间声明的时候
- * @param ctx the parse tree
- */
- @Override
- override fun exitNamespaceDeclaration(ctx: mcfppParser.NamespaceDeclarationContext) {
- Project.currNamespace = ctx.Identifier().text
- }
-
- /**
- * 变量声明
- * @param ctx the parse tree
- */
- @Override
- override fun exitFieldDeclaration(ctx: mcfppParser.FieldDeclarationContext) {
- //变量生成
-
- //变量生成
- val `var`: Var = if (ctx.parent is mcfppParser.ClassMemberContext) {
- return
- } else {
- //函数变量,生成
- Var.build(ctx, Function.currFunction)!!
- }
- //变量注册
- //一定是函数变量
- if (!Function.currFunction.cache.putVar(ctx.Identifier().text, `var`)) {
- Project.logger.error(
- "Duplicate defined variable name:" + ctx.Identifier().text +
- " at " + Project.currFile.name + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- throw VariableDuplicationException()
- }
- Function.addCommand(
- "#" + ctx.type().text + " " + ctx.Identifier()
- .text + if (ctx.expression() != null) " = " + ctx.expression().text else ""
- )
- //变量初始化
- if (ctx.expression() != null) {
- val init: Var = McfppExprVisitor().visit(ctx.expression())!!
- try {
- `var`.assign(init)
- } catch (e: VariableConverseException) {
- Project.logger.error(
- "Cannot convert " + init.javaClass + " to " + `var`.javaClass +
- " at " + Function.currFunction.GetID() + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- throw VariableConverseException()
- }
- }
- }
-
- /**
- * 一个赋值的语句
- * @param ctx the parse tree
- */
- @Override
- override fun exitStatementExpression(ctx: mcfppParser.StatementExpressionContext) {
- Function.addCommand("#" + ctx.text)
- val left: Var = McfppExprVisitor().visit(ctx.basicExpression())!!
- if (left.isConst == Var.ConstStatus.ASSIGNED) {
- Project.logger.error(
- "Cannot assign a constant repeatedly: " + left.key +
- " at " + Function.currFunction.GetID() + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- throw ConstChangeException()
- } else if (left.isConst == Var.ConstStatus.NULL) {
- left.isConst = Var.ConstStatus.ASSIGNED
- }
- val right: Var = McfppExprVisitor().visit(ctx.expression())!!
- try {
- left.assign(right)
- } catch (e: VariableConverseException) {
- Project.logger.error(
- "Cannot convert " + right.javaClass + " to " + left.javaClass +
- " at " + Function.currFunction.GetID() + " line:" + ctx.getStart().line
- )
- Project.errorCount++
- throw VariableConverseException()
- }
- }
-
- /**
- * 自加或自减语句
- * @param ctx the parse tree
- */
- @Override
- override fun exitSelfAddOrMinusStatement(ctx: mcfppParser.SelfAddOrMinusStatementContext) {
- Function.addCommand("#" + ctx.text)
- val re: Var? = Function.currFunction.getVar(ctx.selfAddOrMinusExpression().Identifier().text)
- if (re == null) {
- Project.logger.error(
- "Undefined variable:" + ctx.selfAddOrMinusExpression().Identifier().text +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- Project.errorCount++
- throw VariableNotDefineException()
- }
- if (ctx.selfAddOrMinusExpression().op.text.equals("++")) {
- if (re is MCInt) {
- if (re.isConcrete) {
- re.value = re.value!! + 1
- } else {
- Function.addCommand(Commands.SbPlayerAdd(re, 1))
- }
- }
- } else {
- if (re is MCInt) {
- if (re.isConcrete) {
- re.value = re.value!! - 1
- } else {
- Function.addCommand(Commands.SbPlayerRemove(re, 1))
- }
- }
- }
- }
-
- /**
- * 调用一个函数。参考:
- * [[命令] [数据包] 局部变量、程序控制流程在数据包中的实现 借助汇编语言函数堆栈思想 - mcbbs](https://www.mcbbs.net/thread-1393132-1-1.html)
- * @param ctx the parse tree
- */
- @Override
- override fun exitFunctionCall(ctx: mcfppParser.FunctionCallContext) {
- Function.addCommand("#" + ctx.text)
- //参数获取
- val args: ArrayList = ArrayList()
- val exprVisitor = McfppExprVisitor()
- for (expr in ctx.arguments().expressionList().expression()) {
- args.add(exprVisitor.visit(expr)!!)
- }
- //函数对象获取
- val curr = McfppFuncVisitor().getFunction(ctx, FunctionParam.getVarTypes(args))
- if (curr == null) {
- Project.logger.error(
- "Function " + ctx.text + " not defined " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- throw FunctionNotDefineException()
- }
- if (curr is NativeFunction) {
- //是native方法
- if (curr.isClassMember) {
- //TODO
- throw TODOException("")
- } else {
- curr.invoke(args, ctx.getStart().line)
- }
- return
- }
- curr.invoke(args, ctx.getStart().line)
- //函数树
- Function.currFunction.child.add(curr)
- curr.parent.add(Function.currFunction)
- }
-
- var lastBool: MCBool? = null //if语句的条件
- //TODO 条件判断语句实现方式与参考文章有出入,可能存在bug
- /**
- * 进入if语句块
- * @param ctx the parse tree
- */
- @Override
- override fun enterIfBlock(ctx: mcfppParser.IfBlockContext) {
- Function.addCommand("#if start")
- val parent: mcfppParser.IfStatementContext = ctx.parent as mcfppParser.IfStatementContext
- //是if语句,获取参数
- val index: Int = parent.ifBlock().indexOf(ctx)
- //匿名函数的定义
- val f: Function = InternalFunction("_if_", Function.currFunction)
- Project.global.cache.functions.add(f)
- if (index == 0) {
- //第一个if
- val exp: MCBool = McfppExprVisitor().visit(parent.expression()) as MCBool
- if (exp.isConcrete && exp.value) {
- //函数调用的命令
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(f))
- Project.logger.warn(
- "The condition is always true. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else if (exp.isConcrete) {
- Function.addCommand("#" + Commands.Function(f))
- Project.logger.warn(
- "The condition is always false. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- }
- lastBool = exp
- } else {
- //else语句
- Function.addCommand(
- "execute " +
- "unless score " + lastBool!!.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- }
- Function.currFunction = f
- }
-
- /**
- * 离开if语句块
- * @param ctx the parse tree
- */
- @Override
- override fun exitIfBlock(ctx: mcfppParser.IfBlockContext?) {
- Function.currFunction = Function.currFunction.parent[0]
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.addCommand("#if end")
- }
-
- /**
- * 进入else-if语句块
- * @param ctx the parse tree
- */
- @Override
- override fun enterElseIfStatement(ctx: mcfppParser.ElseIfStatementContext) {
- Function.addCommand("#else if start")
- //匿名函数的定义
- val f: Function = InternalFunction("_if_", Function.currFunction)
- Project.global.cache.functions.add(f)
- if (lastBool!!.isConcrete && !lastBool!!.value) {
- //函数调用的命令
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand("#" + Commands.Function(f))
- Project.logger.warn(
- "The condition is always false. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else if (lastBool!!.isConcrete) {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(f))
- Project.logger.warn(
- "The condition is always true. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "unless score " + lastBool!!.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- }
- lastBool = null
- Function.currFunction = f
- }
-
- /**
- * 离开else-if语句块
- * @param ctx the parse tree
- */
- @Override
- override fun exitElseIfStatement(ctx: mcfppParser.ElseIfStatementContext?) {
- Function.currFunction = Function.currFunction.parent[0]
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.addCommand("#else if end")
- }
-
- /**
- * 进入while语句块
- * @param ctx the parse tree
- */
- @Override
- override fun enterWhileBlock(ctx: mcfppParser.WhileBlockContext) {
- Function.addCommand("#while start")
- val parent: mcfppParser.WhileStatementContext = ctx.parent as mcfppParser.WhileStatementContext
- val exp: MCBool = McfppExprVisitor().visit(parent.expression()) as MCBool
- //匿名函数的定义
- val f: Function = InternalFunction("_while_", Function.currFunction)
- f.child.add(f)
- f.parent.add(f)
- Project.global.cache.functions.add(f)
- if (exp.isConcrete && exp.value) {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(f))
- Project.logger.warn(
- "The condition is always true. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else if (exp.isConcrete) {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand("#" + Commands.Function(f))
- Project.logger.warn(
- "The condition is always false. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- }
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.currFunction = f //后续块中的命令解析到递归的函数中
- }
-
- /**
- * 离开while语句块
- * @param ctx the parse tree
- */
- @Override
- override fun exitWhileBlock(ctx: mcfppParser.WhileBlockContext) {
- if (!Function.isBreak && Function.isLastFunctionEnd != 0) {
- Function.currFunction = Function.currFunction.parent[0]
- }
- //递归调用函数
- //重新计算表达式
- val parent: mcfppParser.WhileStatementContext = ctx.parent as mcfppParser.WhileStatementContext
- val exp: MCBool = McfppExprVisitor().visit(parent.expression()) as MCBool
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(Function.currFunction)
- )
- //调用完毕,将子函数的栈销毁
- Function.currFunction = Function.currFunction.parent[0]
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.addCommand("#while end")
- }
-
- /**
- * 进入do-while语句块,开始匿名函数调用
- * @param ctx the parse tree
- */
- @Override
- override fun enterDoWhileBlock(ctx: mcfppParser.DoWhileBlockContext?) {
- Function.addCommand("#do while start")
- //匿名函数的定义
- val f: Function = InternalFunction("_dowhile_", Function.currFunction)
- f.child.add(f)
- f.parent.add(f)
- Project.global.cache.functions.add(f)
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(f))
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.currFunction = f //后续块中的命令解析到递归的函数中
- }
-
- /**
- * 离开do-while语句
- * @param ctx the parse tree
- */
- @Override
- override fun exitDoWhileStatement(ctx: mcfppParser.DoWhileStatementContext) {
- val exp: MCBool = McfppExprVisitor().visit(ctx.expression()) as MCBool
- if (exp.isConcrete && exp.value) {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(Function.currFunction))
- Project.logger.warn(
- "The condition is always true. " +
- " at " + Project.currFile.name + " line: " + ctx.getStop().line
- )
- } else if (exp.isConcrete) {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand("#" + Commands.Function(Function.currFunction))
- Project.logger.warn(
- "The condition is always false. " +
- " at " + Project.currFile.name + " line: " + ctx.getStop().line
- )
- } else {
- //给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(Function.currFunction)
- )
- }
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- //调用完毕,将子函数的栈销毁
- Function.currFunction = Function.currFunction.parent[0]
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.addCommand("#do while end")
- }
-
- /**
- * 整个for语句本身额外有一个栈,无条件调用函数
- * @param ctx the parse tree
- */
- @Override
- override fun enterForStatement(ctx: mcfppParser.ForStatementContext?) {
- Function.addCommand("#for start")
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- val forFunc: Function = InternalFunction("_for_", Function.currFunction)
- forFunc.parent.add(Function.currFunction)
- Project.global.cache.functions.add(forFunc)
- Function.addCommand(Commands.Function(forFunc))
- Function.currFunction = forFunc
- }
-
- @Override
- override fun exitForStatement(ctx: mcfppParser.ForStatementContext?) {
- Function.currFunction = Function.currFunction.parent[0]
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.addCommand("#for end")
- }
-
- /**
- * 进入for update语句块。
- * 由于在编译过程中,编译器会首先编译for语句的for control部分,也就是for后面的括号,这就意味着forUpdate语句将会先forBlock
- * 被写入到命令函数中。因此我们需要将forUpdate语句中的命令临时放在一个函数内部,然后在forBlock调用完毕后加上中间的命令
- *
- *
- * 值得注意的是,for update和for block相对于整个父函数的栈的位置应该是相同的,如果它们想要调用父函数中声明的变量,都应该
- * 用索引[1]来访问,因此可以直接将for update中的命令转移到for block中而不会出现任何问题。
- *
- * @param ctx the parse tree
- */
- @Override
- override fun enterForUpdate(ctx: mcfppParser.ForUpdateContext?) {
- Function.currFunction = InternalFunction("_forblock_", Function.currFunction)
- }
-
- var forupdate: Function? = null
-
- /**
- * 离开for update。将for update缓存,同时切换当前函数为父函数
- * @param ctx the parse tree
- */
- @Override
- override fun exitForUpdate(ctx: mcfppParser.ForUpdateContext?) {
- forupdate = Function.currFunction
- Function.currFunction = forupdate!!.parent[0]
- }
-
- /**
- * 进入for block语句。此时当前函数为父函数
- * @param ctx the parse tree
- */
- @Override
- override fun enterForBlock(ctx: mcfppParser.ForBlockContext) {
- val parent: mcfppParser.ForStatementContext = ctx.parent as mcfppParser.ForStatementContext
- val exp: MCBool = McfppExprVisitor().visit(parent.forControl().expression()) as MCBool
- //匿名函数的定义。这里才是正式的for函数哦喵
- val f: Function = InternalFunction("_forblock_", Function.currFunction)
- f.child.add(f)
- f.parent.add(f)
- Project.global.cache.functions.add(f)
- if (exp.isConcrete && exp.value) {
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(Commands.Function(f))
- Project.logger.warn(
- "The condition is always true. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else if (exp.isConcrete) {
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand("#" + Commands.Function(f))
- Project.logger.warn(
- "The condition is always false. " +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- } else {
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- }
- //调用完毕,将子函数的栈销毁。这条命令仍然是在for函数中的。
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.currFunction = f //后续块中的命令解析到递归的函数中
- }
-
- /**
- * 离开for block语句。此时当前函数仍然是for的函数
- * @param ctx the parse tree
- */
- @Override
- override fun exitForBlock(ctx: mcfppParser.ForBlockContext) {
- //for update的命令压入
- Function.currFunction.commands.addAll(forupdate!!.commands)
- forupdate = null
- //递归调用函数
- //重新计算表达式
- val parent: mcfppParser.ForStatementContext = ctx.parent as mcfppParser.ForStatementContext
- val exp: MCBool = McfppExprVisitor().visit(parent.forControl().expression()) as MCBool
- //这里就需要给子函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "if score " + exp.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(Function.currFunction)
- )
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.currFunction = Function.currFunction.parent[0]
- }
-
- @Override
- override fun exitOrgCommand(ctx: mcfppParser.OrgCommandContext) {
- Function.addCommand(ctx.text.substring(1))
- }
-
- /**
- * 进入任意语句,检查此函数是否还能继续添加语句
- * @param ctx the parse tree
- */
- @Override
- override fun enterStatement(ctx: mcfppParser.StatementContext) {
- if (Function.currFunction.isEnd) {
- Project.logger.warn(
- "Unreachable code: " + ctx.text +
- " at " + Project.currFile.name + " line: " + ctx.getStart().line
- )
- }
- if (Function.isLastFunctionEnd == 1) {
- //循环经历了break语句的洗礼,后面的语句需要全部放在匿名函数中。
- Function.addCommand("#" + (if (Function.isBreak) "break" else "continue") + " function")
- //匿名函数的定义
- val f: Function = InternalFunction(
- "_" + (if (Function.isBreak) "break" else "continue") + "_",
- Function.currFunction
- )
- f.child.add(f)
- f.parent.add(f)
- Project.global.cache.functions.add(f)
- //给函数开栈
- Function.addCommand("data modify storage mcfpp:system " + Project.name + ".stack_frame prepend value {}")
- Function.addCommand(
- "execute " +
- "unless score " + temp!!.identifier + " " + SbObject.MCS_boolean + " matches 1 " +
- "run " + Commands.Function(f)
- )
- //调用完毕,将子函数的栈销毁
- Function.addCommand("data remove storage mcfpp:system " + Project.name + ".stack_frame[0]")
- Function.currFunction = f //后续块中的命令解析到递归的函数中
- }
- }
-
- private var temp: MCBool? = null
- @Override
- override fun exitControlStatement(ctx: mcfppParser.ControlStatementContext) {
- if (!inLoopStatement(ctx)) {
- Project.logger.error(
- "'continue' or 'break' can only be used in loop statements: " +
- " at " + Project.currFile.getName() + " line: " + ctx.getStart().line
- )
- throw SyntaxException()
- }
- if (Function.currFunction.isEnd || Function.isLastFunctionEnd != 0) {
- return
- }
- Function.addCommand("#" + ctx.text)
- temp = MCBool()
- //变量进栈
- Function.addCommand("scoreboard players set " + temp!!.identifier + " " + SbObject.MCS_boolean + " = " + 1)
- Function.currFunction.isEnd = true
- Function.isLastFunctionEnd = 1
- if (ctx.BREAK() != null) {
- Function.isBreak = true
- }
- }
-
- /**
- * 离开任意代码块。主要用于break语句和continue语句的匿名函数出栈判定。
- * @param ctx the parse tree
- */
- @Override
- override fun exitBlock(ctx: mcfppParser.BlockContext) {
- if (!Function.currFunction.isEnd && Function.isLastFunctionEnd == 2) {
- if (ctx.parent is mcfppParser.IfBlockContext) {
- //如果是if语句,出栈
- Function.currFunction = Function.currFunction.parent.get(0)
- Function.isLastFunctionEnd = 1
- }
- if (ctx.parent is mcfppParser.ForBlockContext
- || ctx.parent is mcfppParser.WhileBlockContext
- || ctx.parent is mcfppParser.DoWhileBlockContext
- ) {
- //是循环语句,出栈的同时重置isLastFunctionEnd标志
- Function.currFunction = Function.currFunction.parent.get(0)
- Function.isLastFunctionEnd = 0
- }
- }
- }
-
- /**
- * 进入类体。
- * @param ctx the parse tree
- */
- @Override
- override fun enterClassBody(ctx: mcfppParser.ClassBodyContext) {
- //获取类的对象
- val parent: mcfppParser.ClassDeclarationContext = ctx.parent as mcfppParser.ClassDeclarationContext
- val identifier: String = parent.className(0).text
- //设置作用域
- Class.currClass = Project.global.cache.classes[identifier]
- Function.currFunction = Class.currClass!!.classPreInit
- }
-
- /**
- * 离开类体。将缓存重新指向全局
- * @param ctx the parse tree
- */
- @Override
- override fun exitClassBody(ctx: mcfppParser.ClassBodyContext?) {
- Class.currClass = null
- Function.currFunction = Function.nullFunction
- }
-
- /**
- * 类成员的声明
- * @param ctx the parse tree
- */
- @Override
- override fun exitClassMemberDeclaration(ctx: mcfppParser.ClassMemberDeclarationContext) {
- val memberContext: mcfppParser.ClassMemberContext = ctx.classMember()
- if (memberContext.classFunctionDeclaration() != null) {
- //函数声明由函数的listener处理
- return
- }
- }
-
- companion object {
- /**
- * 判断这个语句是否在循环语句中。包括嵌套形式。
- * @param ctx 需要判断的语句
- * @return 是否在嵌套中
- */
- private fun inLoopStatement(ctx: RuleContext): Boolean {
- if (ctx is mcfppParser.ForStatementContext) {
- return true
- }
- if (ctx is mcfppParser.DoWhileStatementContext) {
- return true
- }
- if (ctx is mcfppParser.WhileStatementContext) {
- return true
- }
- return if (ctx.parent != null) {
- inLoopStatement(ctx.parent)
- } else false
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/Native.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/Native.kt
deleted file mode 100644
index fa956c0e..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/Native.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-interface Native
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeClass.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/NativeClass.kt
deleted file mode 100644
index a1e3e5bb..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeClass.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-import top.alumopper.mcfpp.Project
-import top.alumopper.mcfpp.lang.*
-import java.lang.reflect.InvocationTargetException
-import java.lang.Class
-
-/**
- * 代表了mcfpp中声明的一个native类
- */
-class NativeClass(identifier: String, namespace: String, cls: Class) : top.alumopper.mcfpp.lib.Class(), Native {
- var cls: Class
-
- constructor(identifier: String, cls: Class) : this(identifier, Project.currNamespace, cls)
-
- init {
- this.identifier = identifier
- this.namespace = namespace
- this.cls = cls
- }
-
- @Throws(
- InvocationTargetException::class,
- NoSuchMethodException::class,
- InstantiationException::class,
- IllegalAccessException::class
- )
- fun newInstance(args: ArrayList): NativeClassObject {
- return NativeClassObject(this, args)
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeConstructor.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/NativeConstructor.kt
deleted file mode 100644
index 9f660c85..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeConstructor.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-import top.alumopper.mcfpp.lang.ClassPointer
-import top.alumopper.mcfpp.lang.Var
-
-class NativeConstructor(cls: Class) : Constructor(cls), Native {
- @Override
- override operator fun invoke(args: ArrayList, lineNo: Int, cls: ClassPointer) {
- TODO()
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeFunction.kt b/src/main/kotlin/top/alumopper/mcfpp/lib/NativeFunction.kt
deleted file mode 100644
index aa548b21..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/lib/NativeFunction.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package top.alumopper.mcfpp.lib
-
-import top.alumopper.mcfpp.exception.IllegalFormatException
-import top.alumopper.mcfpp.lang.ClassPointer
-import top.alumopper.mcfpp.lang.Var
-import java.lang.reflect.InvocationTargetException
-import java.lang.reflect.Method
-import java.lang.Class
-
-/**
- * 表示了一个native方法
- */
-class NativeFunction(name: String, javaMethod: mcfppParser.JavaReferContext?) : Function(name), Native {
- /**
- * native方法引用的java方法的词法上下文
- */
- var javaReferContext: mcfppParser.JavaReferContext?
-
- /**
- * 要调用的java方法
- */
- var javaMethod: Method
-
- /**
- * 引用的java方法的类名。包含包路径
- */
- var javaClassName: String
-
- /**
- * 引用的java方法的参数名。
- */
- var javaMethodName: String
-
- init {
- javaReferContext = javaMethod
- val strs: List = javaMethod!!.stringName()
- try {
- javaMethodName = strs[strs.size - 1].text
- javaClassName = javaMethod.text.substring(0, javaMethod.text.lastIndexOf(javaMethodName) - 1)
- } catch (e: StringIndexOutOfBoundsException) {
- throw IllegalFormatException(javaReferContext!!.text)
- }
- try{
- val cls: Class<*> = Class.forName(javaClassName)
- this.javaMethod = cls.getMethod(javaMethodName, Array::class.java, ClassPointer::class.java)
- } catch (e: NoSuchMethodException) {
- throw NoSuchMethodException(javaMethodName)
- } catch (e: ClassNotFoundException) {
- throw ClassNotFoundException(javaClassName)
- }
- }
-
- @Override
- override operator fun invoke(args: ArrayList, lineNo: Int) {
- val argsArray = arrayOfNulls(args.size)
- args.toArray(argsArray)
- try {
- javaMethod.invoke(null, argsArray, null)
- } catch (e: IllegalAccessException) {
- throw RuntimeException(e)
- } catch (e: InvocationTargetException) {
- throw RuntimeException(e)
- }
- }
-
- @Override
- override operator fun invoke(args: ArrayList, lineNo: Int, cls: ClassPointer) {
- val argsArray = arrayOfNulls(args.size)
- args.toArray(argsArray)
- try {
- javaMethod.invoke(null, argsArray, cls)
- } catch (e: IllegalAccessException) {
- throw RuntimeException(e)
- } catch (e: InvocationTargetException) {
- throw RuntimeException(e)
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/alumopper/mcfpp/package-info.kt b/src/main/kotlin/top/alumopper/mcfpp/package-info.kt
deleted file mode 100644
index 72660f8f..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/package-info.kt
+++ /dev/null
@@ -1,2 +0,0 @@
-package top.alumopper.mcfpp
-
diff --git a/src/main/kotlin/top/alumopper/mcfpp/test/NativeTest1.kt b/src/main/kotlin/top/alumopper/mcfpp/test/NativeTest1.kt
deleted file mode 100644
index f9b1a79a..00000000
--- a/src/main/kotlin/top/alumopper/mcfpp/test/NativeTest1.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package top.alumopper.mcfpp.test
-
-import top.alumopper.mcfpp.lang.ClassPointer
-import top.alumopper.mcfpp.lang.INativeClass
-import top.alumopper.mcfpp.lang.Var
-
-class NativeTest1(vars: Array?, cls: ClassPointer?) : INativeClass(vars, cls) {
- init {
- System.out.println("MNI > Create new Instance!")
- }
-
- companion object {
- fun test(vars: Array, cls: ClassPointer?) {
- System.out.println("MNI > Hello Minecraft!")
- for (v in vars) {
- System.out.println("MNI > Get argument " + v.identifier)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/CompileSettings.kt b/src/main/kotlin/top/mcfpp/CompileSettings.kt
new file mode 100644
index 00000000..e4884d6a
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/CompileSettings.kt
@@ -0,0 +1,13 @@
+package top.mcfpp
+
+object CompileSettings {
+ /**
+ * 是否是debug模式
+ */
+ var isDebug: Boolean = false
+
+ /**
+ * 是否忽略标准库
+ */
+ var ignoreStdLib: Boolean = false
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/MCFPP.kt b/src/main/kotlin/top/mcfpp/MCFPP.kt
new file mode 100644
index 00000000..0d65e7f4
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/MCFPP.kt
@@ -0,0 +1,55 @@
+package top.mcfpp
+
+import org.apache.logging.log4j.core.config.ConfigurationSource
+import org.apache.logging.log4j.core.config.Configurator
+import top.mcfpp.io.DatapackCreator
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.util.LogProcessor
+import top.mcfpp.util.UwU
+import java.io.FileInputStream
+
+/**
+ * 编译器的启动入口
+ */
+fun main(args: Array) {
+ val source: ConfigurationSource
+ try {
+ source = ConfigurationSource(FileInputStream("log4j2.xml"))
+ Configurator.initialize(null, source)
+ } catch (e: Exception) {
+ println("Failed to load log4j2.xml")
+ }
+ if (args.isNotEmpty()) {
+ if (args.size > 1) {
+ if (args.contains("debug")) {
+ CompileSettings.isDebug = true
+ LogProcessor.warn("Compiling in debug mode.")
+ }
+ }
+ val start: Long = System.currentTimeMillis()
+ LogProcessor.info("Tips: " + UwU.tip) //生成tips
+ val path = args[0]
+ Project.readProject(path) //读取配置文件
+ Project.readLib() //读取引用的库的索引
+ Project.init() //初始化
+ Project.indexType() //编制类型索引
+ Project.indexFunction() //编制函数索引
+ Project.compile() //编译
+ Project.optimization() //优化
+ Project.genIndex() //生成索引
+ Project.ctx = null
+ if (Project.config.targetPath != "null") {
+ try {
+ DatapackCreator.createDatapack(Project.config.targetPath) //生成数据包
+ } catch (e: Exception) {
+ LogProcessor.error("Cannot create datapack in path: ${Project.config.targetPath}")
+ }
+ }
+ LogProcessor.info("Finished in " + (System.currentTimeMillis() - start) + "ms")
+ GlobalField.printAll()
+ }
+}
+
+object MCFPP {
+ val version = "0.1.0"
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/Project.kt b/src/main/kotlin/top/mcfpp/Project.kt
new file mode 100644
index 00000000..09121ab4
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/Project.kt
@@ -0,0 +1,402 @@
+package top.mcfpp
+
+import com.alibaba.fastjson2.JSONArray
+import com.alibaba.fastjson2.JSONObject
+import org.antlr.v4.runtime.ParserRuleContext
+import org.antlr.v4.runtime.tree.ParseTree
+import org.apache.logging.log4j.LogManager
+import org.apache.logging.log4j.Logger
+import top.mcfpp.annotations.InsertCommand
+import top.mcfpp.command.CommentType
+import top.mcfpp.io.MCFPPFile
+import top.mcfpp.io.lib.LibReader
+import top.mcfpp.io.lib.LibWriter
+import top.mcfpp.lang.MCFloat
+import top.mcfpp.lang.UnresolvedVar
+import top.mcfpp.lang.Var
+import top.mcfpp.lang.type.MCFPPBaseType
+import top.mcfpp.model.Namespace
+import top.mcfpp.model.Native
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.function.Function
+import top.mcfpp.util.LogProcessor
+import java.io.File
+import java.io.FileReader
+import java.io.IOException
+import java.nio.file.Path
+import kotlin.io.path.absolutePathString
+import kotlin.io.path.name
+
+/**
+ * 一个工程。工程文件包含了这个mcfpp工程编译需要的所有信息。编译器将会以这个文件为入口开始编译。
+ * 同时,这个工程文件的名字也是此文件编译生成的数据包的命名空间。
+ */
+object Project {
+
+ private var logger: Logger = LogManager.getLogger("mcfpp")
+
+ val config = ProjectConfig()
+
+ var ctx: ParserRuleContext? = null
+
+ /**
+ * 当前解析文件的语法树
+ */
+ var trees: MutableMap = mutableMapOf()
+
+ /**
+ * 当前的命名空间
+ */
+ var currNamespace = config.defaultNamespace
+
+ /**
+ * 工程中的总错误数量
+ */
+ private var errorCount = 0
+
+ /**
+ * 工程中的总警告数量
+ */
+ private var warningCount = 0
+
+ lateinit var mcfppTick: Function
+
+ lateinit var mcfppLoad: Function
+
+ lateinit var mcfppInit: Function
+
+ /**
+ * 常量池
+ */
+ val constants: HashMap> = HashMap()
+
+ /**
+ * 宏命令
+ */
+ val macroFunction: LinkedHashMap = LinkedHashMap()
+
+ /**
+ * 初始化
+ */
+ fun init() {
+ //全局缓存初始化
+ GlobalField.init()
+ //初始化mcfpp的tick和load函数
+ //添加命名空间
+ GlobalField.localNamespaces["mcfpp"] = Namespace("mcfpp")
+ mcfppTick = Function("tick", "mcfpp", MCFPPBaseType.Void)
+ mcfppLoad = Function("load", "mcfpp", MCFPPBaseType.Void)
+ mcfppInit = Function("init", "mcfpp", MCFPPBaseType.Void)
+ GlobalField.localNamespaces["mcfpp"]!!.field.addFunction(mcfppLoad, true)
+ GlobalField.localNamespaces["mcfpp"]!!.field.addFunction(mcfppTick, true)
+ GlobalField.localNamespaces["mcfpp"]!!.field.addFunction(mcfppInit, true)
+ GlobalField.functionTags["minecraft:tick"]!!.functions.add(mcfppTick)
+ GlobalField.functionTags["minecraft:load"]!!.functions.add(mcfppLoad)
+ GlobalField.functionTags["minecraft:load"]!!.functions.add(mcfppInit)
+ }
+
+ /**
+ * 读取工程
+ * @param path 工程的json文件的路径
+ */
+ fun readProject(path: String) {
+ //工程信息读取
+ try {
+ //读取json
+ logger.debug("Reading project from file \"$path\"")
+ val reader = FileReader(path)
+ val qwq = File(path)
+ config.root = Path.of(path).parent
+ config.name = qwq.name.substring(0, qwq.name.lastIndexOf('.'))
+ val json = reader.readText()
+ //解析json
+ val jsonObject: JSONObject = JSONObject.parse(json) as JSONObject
+ //代码文件
+ config.files = ArrayList()
+ val filesJson: JSONArray = jsonObject.getJSONArray("files")
+ for (o in filesJson.toArray()) {
+ var s = o as String
+ if (s.endsWith("*")) {
+ //通配符
+ s = s.substring(0, s.length - 1)
+ }
+ val r: File = if (s.length > 2 && s[1] == ':') {
+ //绝对路径
+ File(s)
+ } else {
+ //相对路径
+ File(config.root.absolutePathString() + s)
+ }
+ logger.info("Finding file in \"" + r.absolutePath + "\"")
+ config.files = getFiles(r)
+ }
+ //版本
+ config.version = jsonObject.getString("version")
+ if (config.version == null) {
+ config.version = "1.20"
+ }
+ //描述
+ config.description = jsonObject.getString("description")
+ if (config.description == null) {
+ config.description = "A datapack compiled by MCFPP"
+ }
+ //默认命名空间
+ config.defaultNamespace = if (jsonObject.getString("namespace") != null) {
+ jsonObject.getString("namespace")
+ } else {
+ "default"
+ }
+ //是否包含标准库
+ jsonObject["ignoreStdLib"]?.let {
+ CompileSettings.ignoreStdLib = it as Boolean
+ }
+ //调用库
+ val includesJson: JSONArray = jsonObject.getJSONArray("includes") ?: JSONArray()
+ for (i in 0 until includesJson.size) {
+ config.includes.add(includesJson.getString(i))
+ }
+ //输出目录
+ config.targetPath = jsonObject.getString("targetPath") ?: "out/"
+ } catch (e: Exception) {
+ logger.error("Error while reading project from file \"$path\"")
+ errorCount++
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 读取库文件,并将库写入缓存
+ */
+ fun readLib() {
+ //默认的
+ if (!CompileSettings.ignoreStdLib) {
+ config.includes.addAll(config.stdLib)
+ }
+ //写入缓存
+ for (include in config.includes) {
+ val filePath = if (!include.endsWith("/.mclib")) "$include/.mclib" else include
+ val file = File(filePath)
+ if (file.exists()) {
+ LibReader.read(filePath)
+ } else {
+ LogProcessor.error("Cannot find lib file at: ${file.absolutePath}")
+ }
+ }
+ //库读取完了,现在实例化所有类中的成员字段吧
+ for (namespace in GlobalField.libNamespaces.values) {
+ namespace.field.forEachClass { c ->
+ run {
+ for (v in c.field.allVars) {
+ if (v is UnresolvedVar) {
+ c.field.putVar(c.identifier, v.resolve(c), true)
+ }
+ }
+ for (v in c.staticField.allVars) {
+ if (v is UnresolvedVar) {
+ c.staticField.putVar(c.identifier, v.resolve(c), true)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 编制类型索引
+ */
+ fun indexType() {
+ logger.debug("Generate Type Index...")
+ //解析文件
+ for (file in config.files) {
+ //添加默认库的域
+ if (!CompileSettings.ignoreStdLib) {
+ GlobalField.importedLibNamespaces["mcfpp.sys"] = GlobalField.libNamespaces["mcfpp.sys"]
+ }
+ try {
+ file.indexType()
+ } catch (e: IOException) {
+ logger.error("Error while generate type index in file \"$file\"")
+ errorCount++
+ e.printStackTrace()
+ }
+ GlobalField.importedLibNamespaces.clear()
+ }
+
+ }
+
+ /**
+ * 编制函数索引
+ */
+ fun indexFunction() {
+ logger.debug("Generate Function Index...")
+ //解析文件
+ for (file in config.files) {
+ try {
+ file.indexFunction()
+ } catch (e: IOException) {
+ logger.error("Error while generate function index in file \"$file\"")
+ errorCount++
+ e.printStackTrace()
+ }
+ }
+ }
+
+ /**
+ * 编译工程
+ */
+ fun compile() {
+ //工程文件编译
+ //解析文件
+ for (file in config.files) {
+ LogProcessor.debug("Compiling mcfpp code in \"$file\"")
+ //添加默认库域
+ if (!CompileSettings.ignoreStdLib) {
+ GlobalField.importedLibNamespaces["mcfpp.sys"] = GlobalField.libNamespaces["mcfpp.sys"]
+ }
+ try {
+ file.compile()
+ } catch (e: IOException) {
+ logger.error("Error while compiling file \"$file\"")
+ errorCount++
+ e.printStackTrace()
+ }
+ }
+ }
+
+ /**
+ * 整理并优化工程
+ */
+ @InsertCommand
+ fun optimization() {
+ logger.debug("Optimizing...")
+ logger.debug("Adding scoreboards declare in mcfpp:load function")
+ //region load init command
+ //向load函数中添加记分板初始化命令
+ Function.currFunction =
+ GlobalField.localNamespaces["mcfpp"]!!.field.getFunction("load", ArrayList(), ArrayList())!!
+ for (scoreboard in GlobalField.scoreboards.values) {
+ Function.addCommand("scoreboard objectives add ${scoreboard.name} ${scoreboard.criterion}")
+ }
+ //向load函数中添加库初始化命令
+ Function.addCommand("execute unless score math mcfpp_init matches 1 run function math:_init")
+ //向load中添加类初始化命令
+ for (n in GlobalField.localNamespaces.values) {
+ n.field.forEachClass { c ->
+ run {
+ c.classPreStaticInit.invoke(ArrayList(), callerClassP = null)
+ }
+ }
+ }
+ //浮点数临时marker实体
+ Function.addCommand("summon marker 0 0 0 {Tags:[\"mcfpp:float_marker\"],UUID:${MCFloat.tempFloatEntityUUIDNBT}}")
+ //endregion
+ //浮点数的
+ //寻找入口函数
+ var hasEntrance = false
+ for (field in GlobalField.localNamespaces.values) {
+ field.field.forEachFunction { f ->
+ run {
+ if (f.parent.size == 0 && f !is Native) {
+ //找到了入口函数
+ hasEntrance = true
+ f.commands.add(
+ 0,
+ "data modify storage mcfpp:system ${config.defaultNamespace}.stack_frame prepend value {}"
+ )
+ f.commands.add("data remove storage mcfpp:system ${config.defaultNamespace}.stack_frame[0]")
+ logger.debug("Find entrance function: {} {}", f.tags, f.identifier)
+ }
+ }
+ }
+ }
+ if (!hasEntrance) {
+ logger.warn("No valid entrance function in Project ${config.defaultNamespace}")
+ warningCount++
+ }
+ logger.info("Complete compiling project " + config.root.name + " with [$errorCount] error and [$warningCount] warning")
+ }
+
+ /**
+ * 生成库索引
+ * 在和工程信息json文件的同一个目录下生成一个.mclib文件
+ */
+ fun genIndex() {
+ LibWriter.write(config.root.absolutePathString())
+ }
+
+ /**
+ * 获取文件列表
+ * @param file 根目录
+ * @return 这个根目录下包含的所有文件
+ */
+ private fun getFiles(file: File): ArrayList {
+ val files = ArrayList()
+ if (!file.exists()) {
+ logger.warn("Path \"" + file.absolutePath + "\" doesn't exist. Ignoring.")
+ warningCount++
+ return ArrayList()
+ }
+ val fs: Array = file.listFiles() ?: return ArrayList()
+ for (f in fs) {
+ if (f.isDirectory) //若是目录,则递归打印该目录下的文件
+ files += getFiles(f)
+ if (f.isFile && f.name.substring(f.name.lastIndexOf(".") + 1) == "mcfpp") {
+ if (!files.contains(MCFPPFile(f))) {
+ files.add(MCFPPFile(f))
+ }
+ }
+ }
+ return files
+ }
+}
+
+data class ProjectConfig(
+ /**
+ * 工程对应的mc版本
+ */
+ var version: String? = null,
+
+ /**
+ * 工程的名字
+ */
+ var defaultNamespace: String = "default",
+
+ /**
+ * 数据包输出的文件夹
+ */
+ var targetPath: String = "out/",
+
+ /**
+ * 标准库列表
+ */
+ val stdLib: List = listOf("mcfpp/sys/.mclib", "mcfpp/math/.mclib", "mcfpp/dynamic/.mclib"),
+
+ /**
+ * 注释输出等级
+ */
+ var commentLevel: CommentType = CommentType.DEBUG,
+
+ /**
+ * 工程的根目录
+ */
+ var root: Path = Path.of("."),
+ /**
+ * 工程包含的所有文件
+ */
+ var files: ArrayList = ArrayList(),
+
+ /**
+ * 工程的名字
+ */
+ var name: String = "new_mcfpp_project",
+
+ /**
+ * 数据包的描述。原始Json文本 TODO
+ */
+ var description: String? = null,
+
+ /**
+ * 工程包含的所有引用
+ */
+ var includes: ArrayList = ArrayList()
+)
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/annotations/MCFPNativeProcessor.kt b/src/main/kotlin/top/mcfpp/annotations/MCFPNativeProcessor.kt
new file mode 100644
index 00000000..fc0317f1
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/annotations/MCFPNativeProcessor.kt
@@ -0,0 +1,33 @@
+package top.mcfpp.annotations
+
+import javax.annotation.processing.AbstractProcessor
+import javax.annotation.processing.RoundEnvironment
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.TypeElement
+import javax.tools.Diagnostic
+
+class MCFPNativeProcessor : AbstractProcessor() {
+
+ override fun getSupportedAnnotationTypes(): MutableSet {
+ return mutableSetOf(MCFPPNative::class.java.name)
+ }
+
+ override fun process(annotations: MutableSet?, roundEnv: RoundEnvironment?): Boolean {
+ roundEnv?.getElementsAnnotatedWith(MCFPPNative::class.java)?.forEach { element ->
+ if (element.kind == ElementKind.METHOD) {
+ val methodElement = element as ExecutableElement
+ val parameters = methodElement.parameters
+ if (parameters.size != 2 || parameters[0].asType().toString() != "Var[]" || parameters[1].asType()
+ .toString() != "CanSelectMember"
+ ) {
+ processingEnv.messager.printMessage(
+ Diagnostic.Kind.ERROR,
+ "Method ${methodElement.simpleName} annotated with @MCFPNative must have parameters Var[] vars, CanSelectMember caller"
+ )
+ }
+ }
+ }
+ return true
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppErrorListener.kt b/src/main/kotlin/top/mcfpp/antlr/McfppErrorListener.kt
new file mode 100644
index 00000000..80352c8d
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppErrorListener.kt
@@ -0,0 +1,5 @@
+package top.mcfpp.antlr
+
+import org.antlr.v4.runtime.BaseErrorListener
+
+class McfppErrorListener : BaseErrorListener()
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppExprVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppExprVisitor.kt
new file mode 100644
index 00000000..7f4960a4
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppExprVisitor.kt
@@ -0,0 +1,666 @@
+package top.mcfpp.antlr
+
+import net.querz.nbt.io.SNBTUtil
+import net.querz.nbt.tag.StringTag
+import top.mcfpp.Project
+import top.mcfpp.annotations.InsertCommand
+import top.mcfpp.lang.*
+import top.mcfpp.lang.type.MCFPPGenericClassType
+import top.mcfpp.lang.type.MCFPPType
+import top.mcfpp.lang.value.MCFPPValue
+import top.mcfpp.model.Class
+import top.mcfpp.model.Namespace
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.function.Function
+import top.mcfpp.model.function.FunctionParam
+import top.mcfpp.model.function.NoStackFunction
+import top.mcfpp.model.function.UnknownFunction
+import top.mcfpp.model.generic.Generic
+import top.mcfpp.model.generic.GenericClass
+import top.mcfpp.util.LogProcessor
+import top.mcfpp.util.StringHelper
+import top.mcfpp.util.Utils
+import java.util.*
+import kotlin.system.exitProcess
+
+/**
+ * 获取表达式结果用的visitor。解析并计算一个形如a+b*c的表达式。
+ */
+class McfppExprVisitor(private var defaultGenericClassType: MCFPPGenericClassType? = null) :
+ mcfppParserBaseVisitor?>() {
+
+ private val tempVarCommandCache = HashMap, String>()
+
+ var processVarCache: ArrayList> = ArrayList()
+ fun clearCache() {
+ processVarCache.clear()
+ }
+
+ private var currSelector: CanSelectMember? = null
+
+
+ /**
+ * 计算一个复杂表达式
+ * @param ctx the parse tree
+ * @return 表达式的结果
+ */
+ @Override
+ override fun visitExpression(ctx: mcfppParser.ExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ val l = Function.currFunction
+ val f = NoStackFunction("expression_${UUID.randomUUID()}", Function.currFunction)
+ Function.currFunction = f
+ return if (ctx.primary() != null) {
+ val q = visit(ctx.primary())
+ Function.currFunction = l
+ l.commands.addAll(f.commands)
+ q
+ } else {
+ val q = visit(ctx.conditionalOrExpression())
+ Function.currFunction = l
+ if (q !is ReturnedMCBool) {
+ l.commands.addAll(f.commands)
+ } else {
+ //注册函数
+ if (!GlobalField.localNamespaces.containsKey(f.namespace))
+ GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
+ GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f, false)
+ }
+ q
+ }
+ }
+
+ /*TODO 三目表达式。可能会实现,但是泠雪是懒狐,不想做。
+ *@Override
+ *public Var visitConditionalExpression(mcfppParser.ConditionalExpressionContext ctx){
+ * if(ctx.expression().size() == 0){
+ * return visit(ctx.conditionalOrExpression());
+ * }else {
+ * return null;
+ * }
+ *}
+ */
+
+ /**
+ * 计算一个或表达式。例如 a || b。
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitConditionalOrExpression(ctx: mcfppParser.ConditionalOrExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ if (ctx.conditionalAndExpression().size != 1) {
+ val list = ArrayList()
+ val l = Function.currFunction
+ var isConcrete = true
+ var result = false
+ for (i in 0 until ctx.conditionalAndExpression().size) {
+ val temp = NoStackFunction("bool_${UUID.randomUUID()}", Function.currFunction)
+ //注册函数
+ if (!GlobalField.localNamespaces.containsKey(temp.namespace))
+ GlobalField.localNamespaces[temp.namespace] = Namespace(temp.namespace)
+ GlobalField.localNamespaces[temp.namespace]!!.field.addFunction(temp, false)
+ Function.currFunction = temp
+ val b: Var<*>? = visit(ctx.conditionalAndExpression(i))
+ Function.currFunction = l
+ if (b !is MCBool) {
+ LogProcessor.error("The operator \"&&\" cannot be used with ${b!!.type}")
+ throw IllegalArgumentException("")
+ }
+ if (b is MCFPPValue<*> && isConcrete) {
+ result = result || b.value == true
+ } else {
+ isConcrete = false
+ }
+ }
+ if (isConcrete) {
+ return MCBoolConcrete(result)
+ }
+ for (v in list) {
+ Function.addCommand("execute if function ${v.parentFunction.namespaceID} run return 1")
+ }
+ Function.addCommand("return 0")
+ return ReturnedMCBool(Function.currFunction)
+ } else {
+ return visit(ctx.conditionalAndExpression(0))
+ }
+ }
+
+ /**
+ * 计算一个与表达式。例如a && b
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ //和
+ @Override
+ override fun visitConditionalAndExpression(ctx: mcfppParser.ConditionalAndExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ if (ctx.equalityExpression().size != 1) {
+ val list = ArrayList()
+ val l = Function.currFunction
+ var isConcrete = true
+ var result = true
+ for (i in 0 until ctx.equalityExpression().size) {
+ val temp = NoStackFunction("bool_${UUID.randomUUID()}", Function.currFunction)
+ //注册函数
+ if (!GlobalField.localNamespaces.containsKey(temp.namespace))
+ GlobalField.localNamespaces[temp.namespace] = Namespace(temp.namespace)
+ GlobalField.localNamespaces[temp.namespace]!!.field.addFunction(temp, false)
+ Function.currFunction = temp
+ val b: Var<*>? = visit(ctx.equalityExpression(i))
+ Function.currFunction = l
+ if (b !is MCBool) {
+ LogProcessor.error("The operator \"&&\" cannot be used with ${b!!.type}")
+ throw IllegalArgumentException("")
+ }
+ if (b is MCFPPValue<*> && isConcrete) {
+ result = result && b.value == true
+ } else {
+ isConcrete = false
+ }
+ }
+ if (isConcrete) {
+ return MCBoolConcrete(result)
+ }
+ val sb = StringBuilder("execute ")
+ for (v in list) {
+ sb.append("if function ${v.parentFunction.namespaceID} ")
+ }
+ sb.append("run return 1")
+ Function.addCommand(sb.toString())
+ Function.addCommand("return 0")
+ return ReturnedMCBool(Function.currFunction)
+ } else {
+ return visit(ctx.equalityExpression(0))
+ }
+ }
+
+ /**
+ * 计算一个等于或不等于表达式,例如a == b和a != b
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitEqualityExpression(ctx: mcfppParser.EqualityExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ var re: Var<*>? = visit(ctx.relationalExpression(0))
+ if (ctx.relationalExpression().size != 1) {
+ val b: Var<*>? = visit(ctx.relationalExpression(1))
+ if (!re!!.isTemp) {
+ re = re.getTempVar()
+ }
+ if (ctx.op.text.equals("==")) {
+ re = if (re is MCInt && b is MCInt) {
+ re.isEqual(b)
+ } else if (re is MCBool && b is MCBool) {
+ re.equalCommand(b)
+ } else if (re is MCFloat && b is MCFloat) {
+ re.isEqual(b)
+ } else {
+ LogProcessor.error("The operator \"${ctx.op.text}\" cannot be used between ${re.type} and ${b!!.type}")
+ throw IllegalArgumentException("")
+ }
+ } else {
+ re = if (re is MCInt && b is MCInt) {
+ re.isNotEqual(b)
+ } else if (re is MCBool && b is MCBool) {
+ re.notEqualCommand(b)
+ } else if (re is MCFloat && b is MCFloat) {
+ re.isNotEqual(b)
+ } else {
+ LogProcessor.error("The operator \"${ctx.op.text}\" cannot be used between ${re.type} and ${b!!.type}")
+ throw IllegalArgumentException("")
+ }
+ }
+ }
+ return re
+ }
+
+ /**
+ * 计算一个比较表达式,例如a > b
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitRelationalExpression(ctx: mcfppParser.RelationalExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ var re: Var<*>? = visit(ctx.additiveExpression(0))
+ if (ctx.additiveExpression().size != 1) {
+ val b: Var<*>? = visit(ctx.additiveExpression(1))
+ if (re is MCInt && b is MCInt) {
+ when (ctx.relationalOp().text) {
+ ">" -> re = re.isBigger(b)
+ ">=" -> re = re.isGreaterOrEqual(b)
+ "<" -> re = re.isSmaller(b)
+ "<=" -> re = re.isSmallerOrEqual(b)
+ }
+ } else if (re is MCFloat && b is MCFloat) {
+ when (ctx.relationalOp().text) {
+ ">" -> re = re.isBigger(b)
+ ">=" -> re = re.isGreaterOrEqual(b)
+ "<" -> re = re.isSmaller(b)
+ "<=" -> re = re.isSmallerOrEqual(b)
+ }
+ } else {
+ LogProcessor.error("The operator \"${ctx.relationalOp()}\" cannot be used between ${re!!.type} and ${b!!.type}")
+ throw IllegalArgumentException("")
+ }
+ }
+ return re
+ }
+
+ private var visitAdditiveExpressionRe: Var<*>? = null
+
+ /**
+ * 计算一个加减法表达式,例如a + b
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitAdditiveExpression(ctx: mcfppParser.AdditiveExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ visitAdditiveExpressionRe = visit(ctx.multiplicativeExpression(0))
+ processVarCache.add(visitAdditiveExpressionRe!!)
+ for (i in 1 until ctx.multiplicativeExpression().size) {
+ var b: Var<*>? = visit(ctx.multiplicativeExpression(i))
+ if (b is MCFloat) b = b.toTempEntity()
+ if (visitAdditiveExpressionRe!! != MCFloat.ssObj) {
+ visitAdditiveExpressionRe = visitAdditiveExpressionRe!!.getTempVar()
+ }
+ visitAdditiveExpressionRe = if (Objects.equals(ctx.op.text, "+")) {
+ visitAdditiveExpressionRe!!.plus(b!!)
+ } else if (Objects.equals(ctx.op.text, "-")) {
+ visitAdditiveExpressionRe!!.minus(b!!)
+ } else {
+ null
+ }
+ if (visitAdditiveExpressionRe == null) {
+ LogProcessor.error("The operator \"${ctx.op.text}\" cannot be used between ${visitAdditiveExpressionRe!!.type} and ${b!!.type}.")
+ Utils.stopCompile(IllegalArgumentException(""))
+ exitProcess(1)
+ }
+ processVarCache[processVarCache.size - 1] = visitAdditiveExpressionRe!!
+ }
+ processVarCache.remove(visitAdditiveExpressionRe!!)
+ return visitAdditiveExpressionRe
+ }
+
+ private var visitMultiplicativeExpressionRe: Var<*>? = null
+
+ /**
+ * 计算一个乘除法表达式,例如a * b
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ //乘法
+ @Override
+ override fun visitMultiplicativeExpression(ctx: mcfppParser.MultiplicativeExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ visitMultiplicativeExpressionRe = visit(ctx.unaryExpression(0))
+ processVarCache.add(visitMultiplicativeExpressionRe!!)
+ for (i in 1 until ctx.unaryExpression().size) {
+ var b: Var<*>? = visit(ctx.unaryExpression(i))
+ if (b is MCFloat) b = b.toTempEntity()
+ if (visitMultiplicativeExpressionRe != MCFloat.ssObj) {
+ visitMultiplicativeExpressionRe = visitMultiplicativeExpressionRe!!.getTempVar()
+ }
+ visitMultiplicativeExpressionRe = when (ctx.op.text) {
+ "*" -> {
+ visitAdditiveExpressionRe!!.multiple(b!!)
+ }
+
+ "/" -> {
+ visitAdditiveExpressionRe!!.divide(b!!)
+ }
+
+ "%" -> {
+ visitAdditiveExpressionRe!!.modular(b!!)
+ }
+
+ else -> null
+ }
+ if (visitMultiplicativeExpressionRe == null) {
+ LogProcessor.error("The operator \"${ctx.op.text}\" cannot be used between ${visitMultiplicativeExpressionRe!!.type} and ${b!!.type}.")
+ Utils.stopCompile(IllegalArgumentException(""))
+ exitProcess(1)
+ }
+ processVarCache[processVarCache.size - 1] = visitMultiplicativeExpressionRe!!
+ }
+ processVarCache.remove(visitMultiplicativeExpressionRe!!)
+ return visitMultiplicativeExpressionRe
+ }
+
+ /**
+ * 计算一个单目表达式。比如!a 或者 (int)a
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitUnaryExpression(ctx: mcfppParser.UnaryExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ return if (ctx.rightVarExpression() != null) {
+ visit(ctx.rightVarExpression())
+ } else if (ctx.unaryExpression() != null) {
+ var a: Var<*>? = visit(ctx.unaryExpression())
+ if (a is MCBool) {
+ if (!a.isTemp) {
+ a = a.getTempVar()
+ }
+ a.negation()
+ } else {
+ LogProcessor.error("The operator \"!\" cannot be used with ${a!!.type}")
+ Utils.stopCompile(IllegalArgumentException(""))
+ exitProcess(1)
+ }
+ } else {
+ //类型强制转换
+ visit(ctx.castExpression())
+ }
+ }
+
+
+ /**
+ * 计算一个强制转换表达式。
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitCastExpression(ctx: mcfppParser.CastExpressionContext): Var<*> {
+ Project.ctx = ctx
+ val a: Var<*>? = visit(ctx.unaryExpression())
+ return a!!.cast(MCFPPType.parseFromIdentifier(ctx.type().text, Function.currFunction.field))
+ }
+
+ /**
+ * 对获取到的变量进行包装处理
+ *
+ * @param ctx
+ * @return
+ */
+ @Override
+ override fun visitRightVarExpression(ctx: mcfppParser.RightVarExpressionContext?): Var<*> {
+ return visit(ctx!!.basicExpression())!!
+ //return visit(ctx!!.basicExpression())!!.getTempVar(tempVarCommandCache)
+ }
+
+ /**
+ * 计算一个基本的表达式。可能是一个变量,也可能是一个数值
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitBasicExpression(ctx: mcfppParser.BasicExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ return if (ctx.primary() != null) {
+ visit(ctx.primary())
+ } else {
+ visit(ctx.varWithSelector())
+ }
+ }
+
+ /**
+ * 从类中选择一个成员。返回的成员包含了它所在的对象的信息
+ *
+ * @param ctx
+ * @return
+ */
+ @Override
+ override fun visitVarWithSelector(ctx: mcfppParser.VarWithSelectorContext): Var<*>? {
+ Project.ctx = ctx
+ currSelector = if (ctx.primary() != null) {
+ //从变量中选择(非静态成员)
+ visit(ctx.primary())
+ } else {
+ //从类型中选择(静态成员)
+ //TODO 此处的词法需要更改,className和Identifier有冲突
+ if (ctx.type().className() != null) {
+ //ClassName
+ val clsstr = ctx.type().text.split(":")
+ val qwq: Class? = if (clsstr.size == 2) {
+ GlobalField.getClass(clsstr[0], clsstr[1])
+ } else {
+ GlobalField.getClass(null, clsstr[0])
+ }
+ if (qwq == null) {
+ LogProcessor.error("Undefined class:" + ctx.type().className().text)
+ return UnknownVar("${ctx.type().className().text}_type_" + UUID.randomUUID())
+ }
+ qwq.getType()
+ } else {
+ CompoundDataType(
+ //基本类型
+ when (ctx.type().text) {
+ "int" -> MCInt.data
+ else -> TODO()
+ }
+ )
+ }
+
+ }
+ for (selector in ctx.selector()) {
+ visit(selector)
+ }
+ return currSelector as? Var<*>
+ }
+
+ @Override
+ override fun visitSelector(ctx: mcfppParser.SelectorContext?): Var<*>? {
+ //进入visitVar,currSelector作为成员选择的上下文
+ currSelector = visit(ctx!!.`var`())!!.getTempVar()
+ return null
+ }
+
+ /**
+ * 一个初级表达式,可能是一个变量,也可能是一个数值
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitPrimary(ctx: mcfppParser.PrimaryContext): Var<*>? {
+ Project.ctx = ctx
+ if (ctx.`var`() != null) {
+ //变量
+ return visit(ctx.`var`())
+ } else if (ctx.value() != null) {
+ return visit(ctx.value())
+ } else {
+ //this或者super
+ val re: Var<*>? = Function.field.getVar(ctx.text)
+ if (re == null) {
+ LogProcessor.error("${ctx.text} can only be used in member functions.")
+ }
+ return re
+ }
+ }
+
+ /**
+ * 变量
+ * @param ctx the parse tree
+ * @return 变量
+ */
+ @Override
+ @InsertCommand
+ override fun visitVar(ctx: mcfppParser.VarContext): Var<*>? {
+ Project.ctx = ctx
+ if (ctx.Identifier() != null && ctx.arguments() == null) {
+ //变量
+ //没有数组选取
+ val qwq: String = ctx.Identifier().text
+ var re = if (currSelector == null) {
+ val re: Var<*>? = Function.currFunction.field.getVar(qwq)
+ if (re == null) {
+ LogProcessor.error("Undefined variable:$qwq")
+ throw Exception()
+ }
+ re
+ } else {
+ //获取成员
+ val re = currSelector!!.getMemberVar(qwq, currSelector!!.getAccess(Function.currFunction))
+ if (re.first == null) {
+ LogProcessor.error("Undefined field: $qwq")
+ }
+ if (!re.second) {
+ LogProcessor.error("Cannot access member $qwq")
+ }
+ re.first
+ }
+ // Identifier identifierSuffix*
+ if (ctx.identifierSuffix() == null || ctx.identifierSuffix().size == 0) {
+ return re
+ } else {
+ if (re is Indexable<*>) {
+ for (value in ctx.identifierSuffix()) {
+ val index = visit(value.conditionalExpression())!!
+ re = (re as Indexable<*>).getByIndex(index)
+ }
+ } else {
+ throw IllegalArgumentException("Cannot index ${re!!.type}")
+ }
+ return re
+ }
+ } else if (ctx.expression() != null) {
+ // '(' expression ')'
+ return McfppExprVisitor().visit(ctx.expression())
+ } else {
+ //是函数调用,将已经计算好的中间量存储到栈中
+ for (v in processVarCache) {
+ v.storeToStack()
+ }
+ //函数的调用
+ Function.addCommand("#" + ctx.text)
+ //参数获取
+ val normalArgs: ArrayList> = ArrayList()
+ val readOnlyArgs: ArrayList> = ArrayList()
+ val exprVisitor = McfppExprVisitor()
+ for (expr in ctx.arguments().readOnlyArgs()?.expressionList()?.expression() ?: emptyList()) {
+ val arg = exprVisitor.visit(expr)!!
+ readOnlyArgs.add(arg)
+ }
+ for (expr in ctx.arguments().normalArgs().expressionList()?.expression() ?: emptyList()) {
+ val arg = exprVisitor.visit(expr)!!
+ normalArgs.add(arg)
+ }
+ //获取函数
+ val p = StringHelper.splitNamespaceID(ctx.namespaceID().text)
+ val func = if (currSelector == null) {
+ GlobalField.getFunction(
+ p.first,
+ p.second,
+ FunctionParam.getArgTypeNames(readOnlyArgs),
+ FunctionParam.getArgTypeNames(normalArgs)
+ )
+ } else {
+ if (p.first != null) {
+ LogProcessor.warn("Invalid namespace usage ${p.first} in function call ")
+ }
+ McfppFuncManager().getFunction(
+ currSelector!!, p.second,
+ FunctionParam.getArgTypes(readOnlyArgs),
+ FunctionParam.getArgTypes(normalArgs)
+ )
+ }
+ //调用函数
+ return if (func is UnknownFunction) {
+ var cls: Class? = if (ctx.arguments().readOnlyArgs() != null) {
+ GlobalField.getClass(p.first, p.second, readOnlyArgs.map { it.type })
+ } else {
+ GlobalField.getClass(p.first, p.second)
+ }
+ //可能是构造函数
+ if (cls == null) {
+ LogProcessor.error("Function " + ctx.text + " not defined")
+ Function.addCommand("[Failed to Compile]${ctx.text}")
+ func.invoke(normalArgs, currSelector)
+ return func.returnVar
+ }
+ if (cls is GenericClass) {
+ if (defaultGenericClassType != null) {
+ //比对实例化参数
+ //参数不一致
+ if (defaultGenericClassType!!.genericVar.size != readOnlyArgs.size) {
+ LogProcessor.error("Generic class ${cls.identifier} requires ${cls.readOnlyParams.size} type arguments, but ${readOnlyArgs.size} were provided")
+ return UnknownVar("${cls.identifier}_type_" + UUID.randomUUID())
+ }
+ //参数缺省
+ if (readOnlyArgs.isEmpty()) {
+ readOnlyArgs.addAll(defaultGenericClassType!!.genericVar)
+ }
+ }
+ //实例化泛型函数
+ cls = cls.compile(readOnlyArgs)
+ }
+ //获取对象
+ val ptr = cls.newInstance()
+ //调用构造函数
+ val constructor = cls.getConstructor(FunctionParam.getArgTypeNames(normalArgs))
+ if (constructor == null) {
+ LogProcessor.error("No constructor like: " + FunctionParam.getArgTypeNames(normalArgs) + " defined in class " + ctx.namespaceID().text)
+ Function.addCommand("[Failed to compile]${ctx.text}")
+ } else {
+ constructor.invoke(normalArgs, callerClassP = ptr)
+ }
+ return ptr
+ } else {
+ if (func is Generic<*>) {
+ func.invoke(readOnlyArgs, normalArgs, currSelector)
+ } else {
+ func.invoke(normalArgs, currSelector)
+ }
+ for (v in processVarCache) {
+ v.getFromStack()
+ }
+ //函数树
+ Function.currFunction.child.add(func)
+ func.parent.add(Function.currFunction)
+ func.returnVar
+ }
+ }
+ }
+
+ override fun visitValue(ctx: mcfppParser.ValueContext): Var<*>? {
+ //常量
+ if (ctx.intValue() != null) {
+ return MCIntConcrete(Integer.parseInt(ctx.intValue().text))
+ } else if (ctx.LineString() != null) {
+ val r: String = ctx.LineString().text
+ return MCStringConcrete(StringTag(r.substring(1, r.length - 1)))
+ } else if (ctx.multiLineStringLiteral() != null) {
+ val stringArray = mutableListOf()
+ var isConcrete = true
+ for (stringContext in ctx.multiLineStringLiteral().multiLineStringContent()) {
+ var r: String
+ if (stringContext.MultiLineStrText() != null) r = stringContext.MultiLineStrText().text
+ else if (stringContext.MultiLineStringQuote() != null) r = stringContext.MultiLineStringQuote().text
+ else {
+ val expressionContext = stringContext.multiLineStringExpression().expression()
+ //TODO: 这边只是简单写了一下有解析值的情况
+ val res = visit(expressionContext) //没有解析值的话,应该变成jtext
+ if (res != null && res !is MCFPPValue<*>) {
+ isConcrete = false
+ } //这个条件就是说,整个模版中出现没有解析值的情况了
+ if (res is MCIntConcrete) {
+ r = res.value.toString()
+ } else {
+ r = res.toString()
+ }
+ }
+ stringArray.add(r)
+ }
+ val tailQuote = ctx.multiLineStringLiteral().TRIPLE_QUOTE_CLOSE().text
+ if (tailQuote.length > 3) {
+ stringArray.add(tailQuote.substring(3, tailQuote.length))
+ }
+ return MCStringConcrete(StringTag(stringArray.joinToString(""))) //没有解析值就变不了MCString了
+ } else if (ctx.floatValue() != null) {
+ return MCFloatConcrete(ctx.floatValue()!!.text.toFloat())
+ } else if (ctx.boolValue() != null) {
+ return MCBoolConcrete(ctx.boolValue()!!.text.toBoolean())
+ } else if (ctx.nbtValue() != null) {
+ return NBTBasedDataConcrete(SNBTUtil.fromSNBT(ctx.nbtValue().text))
+ } else if (ctx.type() != null) {
+ return MCFPPTypeVar(MCFPPType.parseFromIdentifier(ctx.type().text, Function.currFunction.field))
+ }
+ return null
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppFieldVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppFieldVisitor.kt
new file mode 100644
index 00000000..4aa4b0ec
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppFieldVisitor.kt
@@ -0,0 +1,921 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.Project
+import top.mcfpp.annotations.InsertCommand
+import top.mcfpp.antlr.mcfppParser.TemplateDeclarationContext
+import top.mcfpp.compiletime.CompileTimeFunction
+import top.mcfpp.exception.*
+import top.mcfpp.exception.IllegalFormatException
+import top.mcfpp.io.MCFPPFile
+import top.mcfpp.lang.*
+import top.mcfpp.lang.type.MCFPPBaseType
+import top.mcfpp.lang.type.MCFPPType
+import top.mcfpp.lang.type.UnresolvedType
+import top.mcfpp.model.*
+import top.mcfpp.model.Member.AccessModifier
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.field.IFieldWithType
+import top.mcfpp.model.function.*
+import top.mcfpp.model.function.Function
+import top.mcfpp.model.generic.GenericExtensionFunction
+import top.mcfpp.model.generic.GenericFunction
+import top.mcfpp.util.LazyWrapper
+import top.mcfpp.util.LogProcessor
+import java.util.*
+import kotlin.Any
+import kotlin.Exception
+import kotlin.IllegalArgumentException
+import kotlin.String
+import kotlin.let
+import kotlin.run
+
+/**
+ * 在编译工程之前,应当首先将所有文件中的资源全部遍历一次并写入缓存。
+ * TODO 存在优化空间,因为部分代码和McfppTypeVisitor有高度重合和相关性
+ */
+open class McfppFieldVisitor : mcfppParserBaseVisitor() {
+
+ protected var isStatic = false
+
+ protected lateinit var typeScope: IFieldWithType
+
+ /**
+ * 遍历整个文件。一个文件包含了命名空间的声明,函数的声明,类的声明以及全局变量的声明。全局变量是可以跨文件调用的。
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitCompilationUnit(ctx: mcfppParser.CompilationUnitContext): Any? {
+ Project.ctx = ctx
+ //命名空间
+ Project.currNamespace = ctx.namespaceDeclaration()?.let {
+ //获取命名空间
+ var namespaceStr = ctx.namespaceDeclaration().Identifier()[0].text
+ if (ctx.namespaceDeclaration().Identifier().size > 1) {
+ ctx.namespaceDeclaration().Identifier().forEach { e ->
+ run {
+ namespaceStr += ".${e.text}"
+ }
+ }
+ }
+ namespaceStr
+ } ?: Project.config.defaultNamespace
+ typeScope = GlobalField.localNamespaces[Project.currNamespace]!!.field
+ //文件结构,类和函数
+ for (t in ctx.typeDeclaration()) {
+ visit(t)
+ }
+ return null
+ }
+
+ /**
+ * 类或函数声明
+ * @param ctx the parse tree
+ * @return null
+ */
+
+ override fun visitDeclarations(ctx: mcfppParser.DeclarationsContext): Any? {
+ Project.ctx = ctx
+ if (ctx.globalDeclaration() != null) {
+ return null
+ }
+ super.visitDeclarations(ctx)
+ return null
+ }
+
+//region interface
+
+ override fun visitInterfaceDeclaration(ctx: mcfppParser.InterfaceDeclarationContext): Any? {
+ Project.ctx = ctx
+ //注册类
+ val id = ctx.classWithoutNamespace().text
+ val namespace = GlobalField.localNamespaces[Project.currNamespace]!!
+
+ if (namespace.field.hasInterface(id)) {
+ //重复声明
+ Interface.currInterface = namespace.field.getInterface(id)
+ } else {
+ throw UndefinedException("Interface Should have been defined: $id")
+ }
+ typeScope = Interface.currInterface!!.field
+ //接口成员
+ for (m in ctx.interfaceBody().interfaceFunctionDeclaration()) {
+ visit(m)
+ }
+ typeScope = MCFPPFile.currFile!!.field
+ return null
+ }
+
+
+ override fun visitInterfaceFunctionDeclaration(ctx: mcfppParser.InterfaceFunctionDeclarationContext): Any? {
+ Project.ctx = ctx
+ //创建函数对象
+ val f = Function(
+ ctx.Identifier().text,
+ Interface.currInterface!!,
+ MCFPPType.parseFromIdentifier(
+ if (ctx.functionReturnType() == null) "void" else ctx.functionReturnType().text,
+ typeScope
+ )
+ )
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //注册函数
+ if (Interface.currInterface!!.field.hasFunction(f)) {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text + "in class " + Class.currClass!!.identifier)
+ Function.currFunction = Function.nullFunction
+ }
+ return null
+ }
+//endregion
+
+//region native class
+ /**
+ * TODO native类的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitNativeClassDeclaration(ctx: mcfppParser.NativeClassDeclarationContext): Any? {
+ //NativeClassVisitor().visit(ctx)
+ return null
+ }
+//endregion
+
+//region class
+ /**
+ * 类的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+
+ override fun visitClassDeclaration(ctx: mcfppParser.ClassDeclarationContext): Any? {
+ Project.ctx = ctx
+ //注册类
+ val id = ctx.classWithoutNamespace().text
+ val namespace = GlobalField.localNamespaces[Project.currNamespace]!!
+ if (ctx.readOnlyParams() != null) {
+ return null
+ }
+ val clazz = if (namespace.field.hasClass(id)) {
+ namespace.field.getClass(id)
+ } else {
+ throw UndefinedException("Class Should have been defined: $id")
+ }
+ Class.currClass = clazz
+ typeScope = Class.currClass!!.field
+ //解析类中的成员
+ //先静态
+ isStatic = true
+ //先解析函数
+ for (c in ctx.classBody().staticClassMemberDeclaration()) {
+ c!!
+ if (c.classMember().classFunctionDeclaration() != null || c.classMember()
+ .abstractClassFunctionDeclaration() != null
+ ) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.classBody().staticClassMemberDeclaration()) {
+ if (c!!.classMember().classFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //后成员
+ isStatic = false
+ //先解析函数和构造函数
+ for (c in ctx.classBody().classMemberDeclaration()) {
+ c!!
+ if (c.classMember() != null && (c.classMember().classFunctionDeclaration() != null || c.classMember()
+ .abstractClassFunctionDeclaration() != null)
+ ) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.classBody().classMemberDeclaration()) {
+ if (c!!.classMember() != null && c.classMember().classFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //如果没有构造函数,自动添加默认的空构造函数
+ if (Class.currClass!!.constructors.size == 0) {
+ Class.currClass!!.addConstructor(Constructor(Class.currClass!!))
+ }
+ //是否为抽象类
+ if (!Class.currClass!!.isAbstract) {
+ var il: Function? = null
+ Class.currClass!!.field.forEachFunction { f ->
+ run {
+ if (f.isAbstract) {
+ il = f
+ return@run
+ }
+ }
+ }
+ if (il != null) {
+ LogProcessor.error("Class ${Class.currClass} must either be declared abstract or implement abstract method ${il!!.nameWithNamespace}")
+ }
+ }
+ Class.currClass = null
+ typeScope = MCFPPFile.currFile!!.field
+ return null
+ }
+
+
+ override fun visitStaticClassMemberDeclaration(ctx: mcfppParser.StaticClassMemberDeclarationContext): Any? {
+ Project.ctx = ctx
+ val m = visit(ctx.classMember()) as Member
+ //访问修饰符
+ if (ctx.accessModifier() != null) {
+ m.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
+ }
+ m.isStatic = true
+ Class.currClass!!.addMember(m)
+ if (m is Function) {
+ m.field.removeVar("this")
+ }
+ return null
+ }
+
+ /**
+ * 类成员的声明。由于函数声明可以后置,因此需要先查明函数声明情况再进行变量的注册以及初始化。
+ *
+ * `classMemberDeclaration
+ * : accessModifier? (STATIC)? classMember
+ * ;
+ `
*
+ * @param ctx the parse tree
+ * @return null
+ */
+
+ override fun visitClassMemberDeclaration(ctx: mcfppParser.ClassMemberDeclarationContext): Any? {
+ Project.ctx = ctx
+ val m = visit(ctx.classMember())
+ if (m is Member) {
+ //访问修饰符
+ if (ctx.accessModifier() != null) {
+ m.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
+ }
+ if (m !is Constructor) {
+ Class.currClass!!.addMember(m)
+ }
+ } else if (m is ArrayList<*>) {
+ //变量列表
+ for (c in m) {
+ c as Member
+ //访问修饰符
+ if (ctx.accessModifier() != null) {
+ c.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
+ }
+ if (c !is Constructor) {
+ Class.currClass!!.addMember(c)
+ }
+ }
+ }
+ return null
+ }
+
+ override fun visitClassMember(ctx: mcfppParser.ClassMemberContext): Any? {
+ Project.ctx = ctx
+ return if (ctx.nativeClassFunctionDeclaration() != null) {
+ visit(ctx.nativeClassFunctionDeclaration())
+ } else if (ctx.classFunctionDeclaration() != null) {
+ visit(ctx.classFunctionDeclaration())
+ } else if (ctx.classFieldDeclaration() != null) {
+ visit(ctx.classFieldDeclaration())
+ } else if (ctx.constructorDeclaration() != null) {
+ visit(ctx.constructorDeclaration())
+ } else {
+ return null
+ }
+ }
+
+ /**
+ * 类方法的声明
+ * @param ctx the parse tree
+ * @return 这个类方法的对象
+ */
+
+ override fun visitClassFunctionDeclaration(ctx: mcfppParser.ClassFunctionDeclarationContext): Any {
+ Project.ctx = ctx
+ val type = MCFPPType.parseFromIdentifier(
+ if (ctx.functionReturnType() == null) "void" else ctx.functionReturnType().text,
+ typeScope
+ )
+ //创建函数对象
+ val f =
+ if (ctx.functionParams().readOnlyParams() != null && ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0
+ ) {
+ GenericFunction(
+ ctx.Identifier().text,
+ Class.currClass!!,
+ ctx.parent is mcfppParser.StaticClassMemberDeclarationContext,
+ type,
+ ctx.functionBody()
+ )
+ } else {
+ Function(
+ ctx.Identifier().text,
+ Class.currClass!!,
+ ctx.parent is mcfppParser.StaticClassMemberDeclarationContext,
+ type
+ )
+ }
+ if (!isStatic) {
+ val thisObj = Var.build("this", MCFPPType.parseFromIdentifier(Class.currClass!!.identifier, typeScope), f)
+ f.field.putVar("this", thisObj)
+ }
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //注册函数
+ if (Class.currClass!!.field.hasFunction(f) || Class.currClass!!.staticField.hasFunction(f)) {
+ if (ctx.OVERRIDE() != null) {
+ if (isStatic) {
+ LogProcessor.error("Cannot override static method ${ctx.Identifier()}")
+ throw Exception()
+ }
+ } else {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text + "in class " + Class.currClass!!.identifier)
+ Function.currFunction = Function.nullFunction
+ }
+ }
+ return f
+ }
+
+
+ override fun visitAbstractClassFunctionDeclaration(ctx: mcfppParser.AbstractClassFunctionDeclarationContext): Any {
+ Project.ctx = ctx
+ val type = MCFPPType.parseFromIdentifier(ctx.functionReturnType().text, typeScope)
+ //抽象函数没有函数体,不能作为GenericFunction
+ //创建函数对象
+ val f = Function(
+ ctx.Identifier().text,
+ Class.currClass!!,
+ ctx.parent is mcfppParser.StaticClassMemberDeclarationContext,
+ type
+ )
+ f.isAbstract = true
+ if (f.isStatic) {
+ LogProcessor.error("Static Function cannot be abstract: ${ctx.Identifier().text} in class ${Class.currClass!!.identifier}")
+ throw Exception()
+ }
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //注册函数
+ if (Class.currClass!!.field.hasFunction(f)) {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text + "in class " + Class.currClass!!.identifier)
+ Function.currFunction = Function.nullFunction
+ }
+ return f
+ }
+
+ override fun visitNativeClassFunctionDeclaration(ctx: mcfppParser.NativeClassFunctionDeclarationContext): Any? {
+ Project.ctx = ctx
+ val nf: NativeFunction = try {
+ //根据JavaRefer找到类
+ val refer = ctx.javaRefer().text
+ val clsName = refer.substring(0, refer.lastIndexOf('.'))
+ val clazz = java.lang.Class.forName(clsName).getConstructor().newInstance()
+ if (clazz !is MNIMethodContainer) {
+ LogProcessor.error("Class $clsName should extends MNIMethodContainer")
+ throw IllegalArgumentException("Class $clsName should extends MNIMethodContainer")
+ }
+ NativeFunction(
+ ctx.Identifier().text,
+ clazz,
+ MCFPPType.parseFromIdentifier(ctx.functionReturnType().text, typeScope),
+ Project.currNamespace
+ )
+ } catch (e: IllegalFormatException) {
+ LogProcessor.error("Illegal Java Method Name: " + e.message)
+ return null
+ } catch (e: ClassNotFoundException) {
+ LogProcessor.error("Cannot find java class: " + e.message)
+ return null
+ } catch (e: NoSuchMethodException) {
+ LogProcessor.error("MNIMethodContainer should have a non-parameter constructor: " + e.message)
+ return null
+ } catch (e: SecurityException) {
+ LogProcessor.error("Cannot access to the constructor: " + e.message)
+ return null
+ }
+ nf.addParamsFromContext(ctx.functionParams())
+ //是类成员
+ nf.ownerType = Function.Companion.OwnerType.CLASS
+ return nf
+ }
+
+ /**
+ * 构造函数的声明
+ * @param ctx the parse tree
+ * @return 这个构造函数的对象
+ */
+ override fun visitConstructorDeclaration(ctx: mcfppParser.ConstructorDeclarationContext): Any {
+ Project.ctx = ctx
+ //类构造函数
+ //创建构造函数对象,注册函数
+ val f = Constructor(Class.currClass!!)
+ f.addParamsFromContext(ctx.normalParams())
+ if (!Class.currClass!!.addConstructor(f)) {
+ LogProcessor.error("Already defined constructor: " + ctx.className().text + "(" + ctx.normalParams().text + ")")
+ }
+ return f
+ }
+
+ /**
+ * 类字段的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+ @InsertCommand
+ override fun visitClassFieldDeclaration(ctx: mcfppParser.ClassFieldDeclarationContext): Any {
+ Project.ctx = ctx
+ //只有类字段构建
+ val reList = ArrayList()
+ val c = ctx.fieldDeclarationExpression()
+ //字段的解析在Analyse阶段结束后,Compile阶段开始的时候进行
+ val type = MCFPPType.parseFromIdentifier(ctx.type().text, typeScope)
+ val `var` = Var.build(c.Identifier().text, type, Class.currClass!!)
+ //是否是静态的
+ if (isStatic) {
+ `var`.isStatic = true
+ `var`.parent = Class.currClass!!.getType()
+ } else {
+ `var`.parent = ClassPointer(Class.currClass!!, "temp")
+ }
+ if (Class.currClass!!.field.containVar(c.Identifier().text)
+ || Class.currClass!!.staticField.containVar(c.Identifier().text)
+ ) {
+ LogProcessor.error("Duplicate defined variable name:" + c.Identifier().text)
+ return reList
+ }
+ //变量的初始化
+ if (c.expression() != null) {
+ Function.currFunction = if (isStatic) {
+ `var`.isStatic = true
+ Class.currClass!!.classPreStaticInit
+ } else {
+ Class.currClass!!.classPreInit
+ }
+ //是类的成员
+ Function.addCommand("#" + ctx.text)
+ val init: Var<*> = McfppExprVisitor().visit(c.expression())!!
+ try {
+ `var`.assign(init)
+ } catch (e: VariableConverseException) {
+ LogProcessor.error("Cannot convert " + init.javaClass + " to " + `var`.javaClass)
+ Function.currFunction = Function.nullFunction
+ throw VariableConverseException()
+ }
+ Function.currFunction = Function.nullFunction
+ `var`.hasAssigned = true
+ }
+ reList.add(`var`)
+ return reList
+ }
+
+//endregion
+
+//region function
+ /**
+ * 函数的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+
+ override fun visitFunctionDeclaration(ctx: mcfppParser.FunctionDeclarationContext): Any? {
+ Project.ctx = ctx
+ //创建函数对象
+ val identifier: String = ctx.Identifier().text
+ val type = MCFPPType.parseFromIdentifier(
+ if (ctx.functionReturnType() == null) "void" else ctx.functionReturnType().text,
+ typeScope
+ )
+ val f =
+ if (ctx.functionParams().readOnlyParams() != null && ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0
+ ) {
+ GenericFunction(identifier, Project.currNamespace, type, ctx.functionBody())
+ } else {
+ Function(identifier, Project.currNamespace, type)
+ }
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //TODO 解析函数的注解
+ //不是类的成员
+ f.ownerType = Function.Companion.OwnerType.NONE
+ //写入域
+ val namespace = GlobalField.localNamespaces[f.namespace]!!
+ if (!namespace.field.hasFunction(f)) {
+ namespace.field.addFunction(f, false)
+ } else {
+ LogProcessor.error("Already defined function:" + f.namespaceID)
+ Function.currFunction = Function.nullFunction
+ }
+ if (f.isEntrance
+ && ctx.functionParams().normalParams().parameterList().parameter().size != 0
+ && (ctx.functionParams().readOnlyParams() == null || ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0)
+ ) {
+ LogProcessor.error("Entrance function shouldn't have parameter:" + f.namespaceID)
+ }
+ return null
+ }
+
+ override fun visitInlineFunctionDeclaration(ctx: mcfppParser.InlineFunctionDeclarationContext): Any? {
+ Project.ctx = ctx
+ //创建函数对象
+ val f: Function
+ //是否是内联函数
+ val identifier: String = ctx.Identifier().text
+ f = InlineFunction(identifier, Project.currNamespace, ctx)
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //TODO 解析函数的注解
+ //不是类的成员
+ f.ownerType = Function.Companion.OwnerType.NONE
+ //写入域
+ val namespace = GlobalField.localNamespaces[f.namespace]!!
+ if (!namespace.field.hasFunction(f)) {
+ namespace.field.addFunction(f, false)
+ } else {
+ LogProcessor.error("Already defined function:" + f.namespaceID)
+ Function.currFunction = Function.nullFunction
+ }
+ if (f.isEntrance
+ && ctx.functionParams().normalParams().parameterList().parameter().size != 0
+ && (ctx.functionParams().readOnlyParams() == null || ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0)
+ ) {
+ LogProcessor.error("Entrance function shouldn't have parameter:" + f.namespaceID)
+ }
+ return null
+ }
+
+ override fun visitCompileTimeFuncDeclaration(ctx: mcfppParser.CompileTimeFuncDeclarationContext): Any? {
+ Project.ctx = ctx
+ //创建函数对象
+ val f: Function
+ //是否是编译时函数
+ val identifier: String = ctx.Identifier().text
+ f = CompileTimeFunction(
+ identifier, Project.currNamespace,
+ MCFPPType.parseFromIdentifier(
+ if (ctx.functionReturnType() == null) "void" else ctx.functionReturnType().text,
+ typeScope
+ ),
+ ctx.functionBody()
+ )
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //TODO 解析函数的注解
+ //不是类的成员
+ f.ownerType = Function.Companion.OwnerType.NONE
+ //写入域
+ val namespace = GlobalField.localNamespaces[f.namespace]!!
+ if (!namespace.field.hasFunction(f)) {
+ f.setField(namespace.field)
+ namespace.field.addFunction(f, false)
+ } else {
+ LogProcessor.error("Already defined function:" + f.namespaceID)
+ Function.currFunction = Function.nullFunction
+ }
+ if (f.isEntrance
+ && ctx.functionParams().normalParams().parameterList().parameter().size != 0
+ && (ctx.functionParams().readOnlyParams() == null || ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0)
+ ) {
+ LogProcessor.error("Entrance function shouldn't have parameter:" + f.namespaceID)
+ }
+ return null
+ }
+
+
+ override fun visitExtensionFunctionDeclaration(ctx: mcfppParser.ExtensionFunctionDeclarationContext?): Any? {
+ Project.ctx = ctx!!
+ val ownerType: Function.Companion.OwnerType
+ //获取被拓展的类
+ val data: CompoundData = if (ctx.type().className() == null) {
+ ownerType = Function.Companion.OwnerType.BASIC
+ when (ctx.type().text) {
+ "int" -> MCInt.data
+ else -> {
+ LogProcessor.error("Cannot add extension function to ${ctx.type().text}")
+ return null
+ }
+ }
+ } else {
+ val clsStr = ctx.type().className().text.split(":")
+ val id: String
+ val nsp: String?
+ if (clsStr.size == 1) {
+ id = clsStr[0]
+ nsp = null
+ } else {
+ id = clsStr[1]
+ nsp = clsStr[0]
+ }
+ val qwq: Class? = GlobalField.getClass(nsp, id)
+ if (qwq == null) {
+ val pwp = GlobalField.getTemplate(nsp, id)
+ if (pwp == null) {
+ LogProcessor.error("Undefined class or struct:" + ctx.type().className().text)
+ return null
+ } else {
+ ownerType = Function.Companion.OwnerType.TEMPLATE
+ pwp
+ }
+ } else {
+ ownerType = Function.Companion.OwnerType.CLASS
+ qwq
+ }
+ }
+ //创建函数对象
+ val f =
+ if (ctx.functionParams().readOnlyParams() != null && ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0
+ ) {
+ GenericExtensionFunction(
+ ctx.Identifier().text,
+ data,
+ Project.currNamespace,
+ MCFPPType.parseFromIdentifier(ctx.functionReturnType().text, typeScope),
+ ctx.functionBody()
+ )
+ } else {
+ ExtensionFunction(
+ ctx.Identifier().text,
+ data,
+ Project.currNamespace,
+ MCFPPType.parseFromIdentifier(ctx.functionReturnType().text, typeScope)
+ )
+ }
+ //解析参数
+ f.accessModifier = AccessModifier.PUBLIC
+ f.ownerType = ownerType
+ f.isStatic = ctx.STATIC() != null
+ f.addParamsFromContext(ctx.functionParams())
+ val field = if (f.isStatic) data.staticField else data.field
+ //注册函数
+ if (!field.addFunction(f, false)) {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text + "in class " + Class.currClass!!.identifier)
+ Function.currFunction = Function.nullFunction
+ }
+ return null
+ }
+
+ /**
+ * native函数的声明
+ * @param ctx the parse tree
+ * @return 如果是全局,返回null,否则返回这个函数对象
+ */
+
+ override fun visitNativeFuncDeclaration(ctx: mcfppParser.NativeFuncDeclarationContext): Any? {
+ Project.ctx = ctx
+ val nf: NativeFunction = try {
+ //根据JavaRefer找到类
+ val refer = ctx.javaRefer().text
+ val clsName = refer.substring(0, refer.lastIndexOf('.'))
+ val clazz = java.lang.Class.forName(clsName).getConstructor().newInstance()
+ if (clazz !is MNIMethodContainer) {
+ LogProcessor.error("Class $clsName should extends MNIMethodContainer")
+ throw IllegalArgumentException("Class $clsName should extends MNIMethodContainer")
+ }
+ NativeFunction(
+ ctx.Identifier().text,
+ clazz,
+ ctx.functionReturnType()?.let { MCFPPType.parseFromContext(it.type(), typeScope) }
+ ?: MCFPPBaseType.Void,
+ Project.currNamespace
+ )
+ } catch (e: IllegalFormatException) {
+ LogProcessor.error("Illegal Java Method Name: " + e.message)
+ return null
+ } catch (e: ClassNotFoundException) {
+ LogProcessor.error("Cannot find java class: " + e.message)
+ return null
+ } catch (e: NoSuchMethodException) {
+ LogProcessor.error("MNIMethodContainer should have a non-parameter constructor: " + e.message)
+ return null
+ } catch (e: SecurityException) {
+ LogProcessor.error("Cannot access to the constructor: " + e.message)
+ return null
+ }
+ nf.addParamsFromContext(ctx.functionParams())
+ //写入域
+ val namespace = GlobalField.localNamespaces[nf.namespace]!!
+ //是普通的函数
+ nf.ownerType = Function.Companion.OwnerType.NONE
+ if (!namespace.field.hasFunction(nf)) {
+ namespace.field.addFunction(nf, false)
+ } else {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text)
+ Function.currFunction = Function.nullFunction
+ }
+ return nf
+ }
+//endregion
+
+ //region template
+ override fun visitTemplateDeclaration(ctx: TemplateDeclarationContext?): Any? {
+ Project.ctx = ctx!!
+ //注册模板
+ val id = ctx.classWithoutNamespace().text
+ val namespace1 = GlobalField.localNamespaces[Project.currNamespace]!!
+ if (namespace1.field.hasTemplate(id)) {
+ //重复声明
+ LogProcessor.error("Template has been defined: $id in namespace ${Project.currNamespace}")
+ Template.currTemplate = namespace1.field.getTemplate(id)
+ }
+ val template = Template(
+ id,
+ LazyWrapper { MCFPPType.parseFromIdentifier(ctx.type().text, typeScope) },
+ Project.currNamespace
+ )
+ if (ctx.className() != null) {
+ //是否存在继承
+ val qwq = ctx.className().text.split(":")
+ val identifier: String
+ val namespace: String?
+ if (qwq.size == 1) {
+ identifier = qwq[0]
+ namespace = null
+ } else {
+ namespace = qwq[0]
+ identifier = qwq[1]
+ }
+ val s = GlobalField.getTemplate(namespace, identifier)
+ if (s == null) {
+ LogProcessor.error("Undefined struct: " + ctx.className().text)
+ } else {
+ template.parent.add(s)
+ }
+ }
+ namespace1.field.addTemplate(id, template)
+ Template.currTemplate = template
+ typeScope = template.field
+ //解析成员
+ //先静态
+ isStatic = true
+ //先解析函数
+ for (c in ctx.templateBody().staticTemplateMemberDeclaration()) {
+ if (c!!.templateMember().templateFunctionDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.templateBody().staticTemplateMemberDeclaration()) {
+ if (c!!.templateMember().templateFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //后成员
+ isStatic = false
+ //先解析函数和构造函数
+ for (c in ctx.templateBody().templateMemberDeclaration()) {
+ if (c!!.templateMember().templateFunctionDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.templateBody().templateMemberDeclaration()) {
+ if (c!!.templateMember().templateFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ Template.currTemplate = null
+ typeScope = MCFPPFile.currFile!!.field
+ return null
+ }
+
+
+ override fun visitStaticTemplateMemberDeclaration(ctx: mcfppParser.StaticTemplateMemberDeclarationContext): Any? {
+ Project.ctx = ctx
+ val m = visit(ctx.templateMember()) as Member
+ //访问修饰符
+ if (ctx.accessModifier() != null) {
+ m.accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
+ }
+ m.isStatic = true
+ Template.currTemplate!!.addMember(m)
+ if (m is Function) {
+ m.field.removeVar("this")
+ }
+ return null
+ }
+
+ /**
+ * 类成员的声明。由于函数声明可以后置,因此需要先查明函数声明情况再进行变量的注册以及初始化。
+ *
+ * `classMemberDeclaration
+ * : accessModifier? (STATIC)? classMember
+ * ;
+ `
*
+ * @param ctx the parse tree
+ * @return null
+ */
+
+ override fun visitTemplateMemberDeclaration(ctx: mcfppParser.TemplateMemberDeclarationContext): Any? {
+ Project.ctx = ctx
+ val m = visit(ctx.templateMember())
+ val accessModifier = AccessModifier.valueOf(ctx.accessModifier().text.uppercase(Locale.getDefault()))
+ //访问修饰符
+ if (m is Member) {
+ if (ctx.accessModifier() != null) {
+ m.accessModifier = accessModifier
+ }
+ } else if (m is ArrayList<*>) {
+ for (v in m) {
+ (v as Var<*>).accessModifier = accessModifier
+ }
+ }
+ return null
+ }
+
+
+ override fun visitTemplateMember(ctx: mcfppParser.TemplateMemberContext): Any? {
+ Project.ctx = ctx
+ return if (ctx.templateFunctionDeclaration() != null) {
+ visit(ctx.templateFunctionDeclaration())
+ } else if (ctx.templateFieldDeclaration() != null) {
+ visit(ctx.templateFieldDeclaration())
+ } else {
+ return null
+ }
+ }
+
+ override fun visitTemplateFunctionDeclaration(ctx: mcfppParser.TemplateFunctionDeclarationContext): Any {
+ Project.ctx = ctx
+ val type = MCFPPType.parseFromIdentifier(
+ if (ctx.functionReturnType() == null) "void" else ctx.functionReturnType().text,
+ typeScope
+ )
+ //创建函数对象
+ val f =
+ if (ctx.functionParams().readOnlyParams() != null && ctx.functionParams().readOnlyParams().parameterList()
+ .parameter().size != 0
+ ) {
+ GenericFunction(
+ ctx.Identifier().text,
+ Template.currTemplate!!,
+ ctx.parent is mcfppParser.StaticTemplateMemberDeclarationContext,
+ type,
+ ctx.functionBody()
+ )
+ } else {
+ Function(
+ ctx.Identifier().text,
+ Template.currTemplate!!,
+ ctx.parent is mcfppParser.StaticTemplateMemberDeclarationContext,
+ type
+ )
+ }
+ if (!isStatic) {
+ val varType = Template.currTemplate!!.getType()
+ val thisObj = Var.build("this", varType, f)
+ f.field.putVar("this", thisObj)
+ }
+ //解析参数
+ f.addParamsFromContext(ctx.functionParams())
+ //注册函数
+ if (Template.currTemplate!!.field.hasFunction(f) || Template.currTemplate!!.staticField.hasFunction(f)) {
+ LogProcessor.error("Already defined function:" + ctx.Identifier().text + "in struct " + Template.currTemplate!!.identifier)
+ Function.currFunction = Function.nullFunction
+ }
+ return f
+ }
+
+ override fun visitTemplateFieldDeclaration(ctx: mcfppParser.TemplateFieldDeclarationContext): ArrayList> {
+ Project.ctx = ctx
+ val re = ArrayList>()
+ for (i in ctx.templateFieldDeclarationExpression()) {
+ //变量生成
+ val `var` = visit(i) as Var<*>
+ re.add(`var`)
+ }
+ return re
+ }
+
+ override fun visitTemplateFieldDeclarationExpression(ctx: mcfppParser.TemplateFieldDeclarationExpressionContext): Var<*>? {
+ //TODO 地狱绘图(指parent串)
+ val `var` = UnresolvedVar(
+ ctx.Identifier().text,
+ UnresolvedType((ctx.parent.parent.parent.parent.parent as TemplateDeclarationContext).type().text),
+ typeScope
+ )
+ //是否是静态的
+ `var`.isStatic = isStatic
+ //只有可能是结构体成员
+ if (Template.currTemplate!!.field.containVar(ctx.Identifier().text) || Template.currTemplate!!.staticField.containVar(
+ ctx.Identifier().text
+ )
+ ) {
+ LogProcessor.error("Duplicate defined variable name:" + ctx.Identifier().text)
+ return null
+ }
+ return `var`
+ }
+
+ //endregion
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppFuncManager.kt b/src/main/kotlin/top/mcfpp/antlr/McfppFuncManager.kt
new file mode 100644
index 00000000..38df14b8
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppFuncManager.kt
@@ -0,0 +1,114 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.lang.CanSelectMember
+import top.mcfpp.lang.ClassPointer
+import top.mcfpp.lang.CompoundDataType
+import top.mcfpp.lang.Var
+import top.mcfpp.lang.type.MCFPPType
+import top.mcfpp.model.Member
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.function.Function
+import top.mcfpp.util.LogProcessor
+import kotlin.reflect.KFunction
+
+/**
+ * 获取函数用的visitor
+ */
+class McfppFuncManager {
+
+ /**
+ * 获取一个全局函数
+ *
+ * @param namespace
+ * @param identifier
+ * @param normalParams
+ * @return
+ */
+ fun getFunction(
+ namespace: String?,
+ identifier: String,
+ readOnlyParams: List,
+ normalParams: ArrayList
+ ): Function {
+ return GlobalField.getFunction(namespace, identifier, readOnlyParams, normalParams)
+ }
+
+ /**
+ * 获取成员函数
+ *
+ * @param curr 一个变量,用于从中选择函数
+ * @param identifier 函数的名字
+ * @param readOnlyParams 函数的只读参数
+ * @param normalParams 函数的普通参数
+ * @return
+ */
+ fun getFunction(
+ curr: Var<*>,
+ identifier: String,
+ readOnlyParams: List,
+ normalParams: ArrayList
+ ): Function {
+ //是类的成员方法或扩展方法
+ val getter: KFunction> = curr::getMemberFunction
+ val accessModifier: Member.AccessModifier = if (curr is ClassPointer) {
+ //类指针
+ if (Function.currFunction.ownerType == Function.Companion.OwnerType.CLASS) {
+ Function.currFunction.parentClass()!!.getAccess(curr.clsType)
+ } else {
+ Member.AccessModifier.PUBLIC
+ }
+ } else {
+ //基本类型
+ Member.AccessModifier.PUBLIC
+ }
+ //开始选择函数
+ val func = getter.call(identifier, readOnlyParams, normalParams, accessModifier)
+ if (!func.second) {
+ LogProcessor.error("Cannot access member $identifier")
+ }
+ return func.first
+ }
+
+
+ /**
+ * 获取一个类的静态函数
+ *
+ * @param type
+ * @param identifier
+ * @param readOnlyParams
+ * @param normalParams
+ * @return
+ */
+ fun getFunction(
+ type: CompoundDataType,
+ identifier: String,
+ readOnlyParams: List,
+ normalParams: ArrayList
+ ): Function {
+ //是类的成员方法
+ val accessModifier = if (Function.currFunction.ownerType == Function.Companion.OwnerType.CLASS) {
+ Function.currFunction.parentClass()!!.getAccess(type.dataType)
+ } else {
+ Member.AccessModifier.PUBLIC
+ }
+ //开始选择函数
+ val func = type.getMemberFunction(identifier, readOnlyParams, normalParams, accessModifier)
+ if (!func.second) {
+ LogProcessor.error("Cannot access member $identifier in class ${type.dataType.identifier}")
+ }
+ return func.first
+ }
+
+ fun getFunction(
+ selector: CanSelectMember,
+ identifier: String,
+ readOnlyParams: List,
+ normalParams: ArrayList
+ ): Function {
+ return when (selector) {
+ is CompoundDataType -> getFunction(selector, identifier, readOnlyParams, normalParams)
+ is Var<*> -> getFunction(selector, identifier, readOnlyParams, normalParams)
+ else -> throw Exception()
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassFieldVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassFieldVisitor.kt
new file mode 100644
index 00000000..c936321c
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassFieldVisitor.kt
@@ -0,0 +1,75 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.Project
+import top.mcfpp.io.MCFPPFile
+import top.mcfpp.model.Class
+import top.mcfpp.model.function.Constructor
+import top.mcfpp.model.function.Function
+import top.mcfpp.util.LogProcessor
+
+class McfppGenericClassFieldVisitor(val clazz: Class) : McfppFieldVisitor() {
+ override fun visitClassDeclaration(ctx: mcfppParser.ClassDeclarationContext): Any? {
+ Project.ctx = ctx
+
+ Class.currClass = clazz
+
+ typeScope = Class.currClass!!.field
+ //解析类中的成员
+ //先静态
+ isStatic = true
+ //先解析函数
+ for (c in ctx.classBody().staticClassMemberDeclaration()) {
+ c!!
+ if (c.classMember().classFunctionDeclaration() != null || c.classMember()
+ .abstractClassFunctionDeclaration() != null
+ ) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.classBody().staticClassMemberDeclaration()) {
+ if (c!!.classMember().classFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //后成员
+ isStatic = false
+ //先解析函数和构造函数
+ for (c in ctx.classBody().classMemberDeclaration()) {
+ c!!
+ if (c.classMember() != null && (c.classMember().classFunctionDeclaration() != null || c.classMember()
+ .abstractClassFunctionDeclaration() != null)
+ ) {
+ visit(c)
+ }
+ }
+ //再解析变量
+ for (c in ctx.classBody().classMemberDeclaration()) {
+ if (c!!.classMember() != null && c.classMember().classFieldDeclaration() != null) {
+ visit(c)
+ }
+ }
+ //如果没有构造函数,自动添加默认的空构造函数
+ if (Class.currClass!!.constructors.size == 0) {
+ Class.currClass!!.addConstructor(Constructor(Class.currClass!!))
+ }
+ //是否为抽象类
+ if (!Class.currClass!!.isAbstract) {
+ var il: Function? = null
+ Class.currClass!!.field.forEachFunction { f ->
+ run {
+ if (f.isAbstract) {
+ il = f
+ return@run
+ }
+ }
+ }
+ if (il != null) {
+ LogProcessor.error("Class ${Class.currClass} must either be declared abstract or implement abstract method ${il!!.nameWithNamespace}")
+ }
+ }
+ Class.currClass = null
+ typeScope = MCFPPFile.currFile!!.field
+ return null
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassImVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassImVisitor.kt
new file mode 100644
index 00000000..82437179
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppGenericClassImVisitor.kt
@@ -0,0 +1,36 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.Project
+import top.mcfpp.model.Class
+import top.mcfpp.model.function.Function
+
+class McfppGenericClassImVisitor : McfppImVisitor() {
+
+ override fun visitClassBody(ctx: mcfppParser.ClassBodyContext): Any? {
+ enterClassBody(ctx)
+ visitChildren(ctx)
+ exitClassBody(ctx)
+ return null
+ }
+
+ /**
+ * 进入类体。
+ * @param ctx the parse tree
+ */
+ private fun enterClassBody(ctx: mcfppParser.ClassBodyContext) {
+ Project.ctx = ctx
+ //TODO 注解
+ }
+
+ /**
+ * 离开类体。将缓存重新指向全局
+ * @param ctx the parse tree
+ */
+
+ private fun exitClassBody(ctx: mcfppParser.ClassBodyContext) {
+ Project.ctx = ctx
+ Class.currClass = null
+ Function.currFunction = Function.nullFunction
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppImVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppImVisitor.kt
new file mode 100644
index 00000000..232e686a
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppImVisitor.kt
@@ -0,0 +1,1188 @@
+package top.mcfpp.antlr
+
+import org.antlr.v4.runtime.RuleContext
+import top.mcfpp.Project
+import top.mcfpp.annotations.InsertCommand
+import top.mcfpp.antlr.mcfppParser.CompileTimeFuncDeclarationContext
+import top.mcfpp.command.CommandList
+import top.mcfpp.command.Commands
+import top.mcfpp.exception.VariableConverseException
+import top.mcfpp.io.MCFPPFile
+import top.mcfpp.lang.*
+import top.mcfpp.lang.type.MCFPPBaseType
+import top.mcfpp.lang.type.MCFPPGenericClassType
+import top.mcfpp.lang.type.MCFPPType
+import top.mcfpp.lang.value.MCFPPValue
+import top.mcfpp.model.*
+import top.mcfpp.model.Annotation
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.function.Function
+import top.mcfpp.model.function.FunctionParam
+import top.mcfpp.model.function.FunctionParam.Companion.typeToStringList
+import top.mcfpp.model.function.InternalFunction
+import top.mcfpp.model.function.UnknownFunction
+import top.mcfpp.model.generic.Generic
+import top.mcfpp.util.LogProcessor
+
+open class McfppImVisitor : mcfppParserBaseVisitor() {
+
+ override fun visitTopStatement(ctx: mcfppParser.TopStatementContext): Any? {
+ if (ctx.statement().size == 0) return null
+ Function.currFunction = MCFPPFile.currFile!!.topFunction
+ //注册函数
+ GlobalField.localNamespaces[Project.currNamespace]!!.field.addFunction(Function.currFunction, force = false)
+ super.visitTopStatement(ctx)
+ Function.currFunction = Function.nullFunction
+ return null
+ }
+
+ override fun visitFunctionDeclaration(ctx: mcfppParser.FunctionDeclarationContext): Any? {
+ if (ctx.parent is CompileTimeFuncDeclarationContext) return null
+ enterFunctionDeclaration(ctx)
+ super.visitFunctionDeclaration(ctx)
+ exitFunctionDeclaration(ctx)
+ return null
+ }
+
+ private fun enterFunctionDeclaration(ctx: mcfppParser.FunctionDeclarationContext) {
+ Project.ctx = ctx
+ val f: Function
+ //获取函数对象
+ val types = FunctionParam.parseReadonlyAndNormalParamTypes(ctx.functionParams())
+ //获取缓存中的对象
+ f = GlobalField.getFunctionInner(Project.currNamespace, ctx.Identifier().text, types.first, types.second)
+ Function.currFunction = f
+ //对函数进行注解处理
+ for (a in annoInCompound) {
+ a.forFunction(f)
+ }
+ annoInCompound.clear()
+ }
+
+ private fun exitFunctionDeclaration(ctx: mcfppParser.FunctionDeclarationContext) {
+ Project.ctx = ctx
+ //函数是否有返回值
+ if (Function.currFunction !is Generic<*> && Function.currFunction.returnType != MCFPPBaseType.Void && !Function.currFunction.hasReturnStatement) {
+ LogProcessor.error("A 'return' expression required in function: " + Function.currFunction.namespaceID)
+ }
+ Function.currFunction = Function.nullFunction
+ if (Class.currClass == null) {
+ //不在类中
+ Function.currFunction = Function.nullFunction
+ } else {
+ Function.currFunction = Class.currClass!!.classPreInit
+ }
+ }
+
+ override fun visitFunctionBody(ctx: mcfppParser.FunctionBodyContext): Any? {
+ if (ctx.parent is CompileTimeFuncDeclarationContext) return null
+ if (Function.currFunction !is Generic<*>) {
+ super.visitFunctionBody(ctx)
+ }
+ return null
+ }
+
+
+ //泛型函数编译使用的入口
+ fun visitFunctionBody(ctx: mcfppParser.FunctionBodyContext, function: Function) {
+ val lastFunction = Function.currFunction
+ Function.currFunction = function
+ super.visitFunctionBody(ctx)
+ Function.currFunction = lastFunction
+ }
+
+ /**
+ * 进入命名空间声明的时候
+ * @param ctx the parse tree
+ */
+ override fun visitNamespaceDeclaration(ctx: mcfppParser.NamespaceDeclarationContext): Any? {
+ Project.ctx = ctx
+ Project.currNamespace = ctx.Identifier(0).text
+ if (ctx.Identifier().size > 1) {
+ for (n in ctx.Identifier().subList(1, ctx.Identifier().size - 1)) {
+ Project.currNamespace += ".$n"
+ }
+ }
+ MCFPPFile.currFile!!.topFunction.namespace = Project.currNamespace
+ return null
+ }
+
+ /**
+ * 变量声明
+ * @param ctx the parse tree
+ */
+ @InsertCommand
+ override fun visitFieldDeclaration(ctx: mcfppParser.FieldDeclarationContext): Any? {
+ Project.ctx = ctx
+ //变量生成
+ val fieldModifier = ctx.fieldModifier()?.text
+ if (ctx.parent is mcfppParser.ClassMemberContext) {
+ return null
+ }
+ if (ctx.VAR() != null) {
+ //自动判断类型
+ val init: Var<*> = McfppExprVisitor().visit(ctx.expression())!!
+ val `var` = Var.build(ctx.Identifier().text, init.type, Function.currFunction)
+ //变量注册
+ //一定是函数变量
+ if (!Function.field.putVar(ctx.Identifier().text, `var`, true)) {
+ LogProcessor.error("Duplicate defined variable name:" + ctx.Identifier().text)
+ }
+ try {
+ if (`var` is MCInt && init is MCInt && init !is MCIntConcrete) {
+ Function.currFunction.commands.replaceThenAnalyze(
+ init.name to `var`.name,
+ init.`object`.name to `var`.`object`.name
+ )
+ `var`.assignCommand(init, Function.currFunction.commands.last().toString())
+ } else {
+ `var`.assign(init)
+ }
+ } catch (e: VariableConverseException) {
+ LogProcessor.error("Cannot convert " + init.javaClass + " to " + `var`.javaClass)
+ throw VariableConverseException()
+ }
+ when (fieldModifier) {
+ "const" -> {
+ if (!`var`.hasAssigned) {
+ LogProcessor.error("The const field ${`var`.identifier} must be initialized.")
+ }
+ `var`.isConst = true
+ }
+
+ "dynamic" -> {
+ if (`var` is MCFPPValue<*>) {
+ `var`.toDynamic(true)
+ }
+ }
+
+ "import" -> {
+ `var`.isImport = true
+ }
+ }
+ } else {
+ for (c in ctx.fieldDeclarationExpression()) {
+ val type = MCFPPType.parseFromContext(ctx.type(), Function.currFunction.field)
+ //函数变量,生成
+ var `var` = Var.build(c.Identifier().text, type, Function.currFunction)
+ //变量注册
+ //一定是函数变量
+ if (Function.field.containVar(c.Identifier().text)) {
+ LogProcessor.error("Duplicate defined variable name:" + c.Identifier().text)
+ }
+ Function.addCommand("#field: " + ctx.type().text + " " + c.Identifier().text + if (c.expression() != null) " = " + c.expression().text else "")
+ //变量初始化
+ if (c.expression() != null) {
+ val init: Var<*> =
+ McfppExprVisitor(if (type is MCFPPGenericClassType) type else null).visit(c.expression())!!
+ try {
+ if (`var` is MCInt && init is MCInt && init !is MCIntConcrete) {
+ Function.currFunction.commands.replaceThenAnalyze(
+ init.name to `var`.name,
+ init.`object`.name to `var`.`object`.name
+ )
+ `var` = `var`.assignCommand(init, Function.currFunction.commands.last().toString())
+ } else {
+ `var` = `var`.assign(init)
+ }
+ } catch (e: VariableConverseException) {
+ LogProcessor.error("Cannot convert " + init.javaClass + " to " + `var`.javaClass)
+ throw VariableConverseException(e)
+ }
+ }
+ Function.field.putVar(`var`.identifier, `var`, true)
+ when (fieldModifier) {
+ "const" -> {
+ if (!`var`.hasAssigned) {
+ LogProcessor.error("The const field ${`var`.identifier} must be initialized.")
+ }
+ `var`.isConst = true
+ }
+
+ "dynamic" -> {
+ if (`var` is MCFPPValue<*>) {
+ `var`.toDynamic(true)
+ }
+ }
+
+ "import" -> {
+ `var`.isImport = true
+ }
+ }
+ }
+ }
+ return null
+ }
+
+ /**
+ * 一个赋值的语句
+ * @param ctx the parse tree
+ */
+ @InsertCommand
+ override fun visitStatementExpression(ctx: mcfppParser.StatementExpressionContext): Any? {
+ Project.ctx = ctx
+ Function.addCommand("#expression: " + ctx.text)
+ val right: Var<*> = McfppExprVisitor().visit(ctx.expression())!!
+ if (ctx.basicExpression() != null) {
+ val left: Var<*> = McfppLeftExprVisitor().visit(ctx.basicExpression())!!
+ if (left.isConst) {
+ LogProcessor.error("Cannot assign a constant repeatedly: " + left.identifier)
+ return null
+ }
+ try {
+ if (left is MCInt && right is MCInt) {
+ Function.currFunction.commands.replaceThenAnalyze(
+ right.name to left.name,
+ right.`object`.name to left.`object`.name
+ )
+ left.replacedBy(left.assignCommand(right, Function.currFunction.commands.last().toString()))
+ } else {
+ left.replacedBy(left.assign(right))
+ }
+ } catch (e: VariableConverseException) {
+ LogProcessor.error("Cannot convert " + right.javaClass + " to " + left.javaClass)
+ throw VariableConverseException()
+ }
+ } else {
+ //TODO 只有一个表达式的计算
+ }
+ Function.addCommand("#expression end: " + ctx.text)
+ return null
+ }
+
+ val annoInGlobal = ArrayList()
+ val annoInCompound = ArrayList()
+
+ /**
+ * 自加或自减语句
+ * TODO
+ * @param ctx the parse tree
+ */
+ /*
+ * override fun exitSelfAddOrMinusStatement(ctx: mcfppParser.SelfAddOrMinusStatementContext) {
+ * Project.ctx = ctx
+ * Function.addCommand("#" + ctx.text)
+ * val re: Var? = Function.field.getVar(ctx.selfAddOrMinusExpression().Identifier().text)
+ * if (re == null) {
+ * LogProcessor.error("Undefined variable:" + ctx.selfAddOrMinusExpression().Identifier().text)
+ * throw VariableNotDefineException()
+ * }
+ * if (ctx.selfAddOrMinusExpression().op.text.equals("++")) {
+ * if (re is MCInt) {
+ * if (re.isConcrete) {
+ * re.value = re.value!! + 1
+ * } else {
+ * Function.addCommand(Commands.SbPlayerAdd(re, 1))
+ * }
+ * }
+ * } else {
+ * if (re is MCInt) {
+ * if (re.isConcrete) {
+ * re.value = re.value!! - 1
+ * } else {
+ * Function.addCommand(Commands.SbPlayerRemove(re, 1))
+ * }
+ * }
+ * }
+ * }
+ */
+
+ override fun visitExtensionFunctionDeclaration(ctx: mcfppParser.ExtensionFunctionDeclarationContext): Any? {
+ //是扩展函数
+ enterExtensionFunctionDeclaration(ctx)
+ super.visitExtensionFunctionDeclaration(ctx)
+ exitExtensionFunctionDeclaration(ctx)
+
+ return null
+ }
+
+ fun enterExtensionFunctionDeclaration(ctx: mcfppParser.ExtensionFunctionDeclarationContext) {
+ val f: Function
+ val data: CompoundData = if (ctx.type().className() == null) {
+ when (ctx.type().text) {
+ "int" -> MCInt.data
+ else -> {
+ throw Exception("Cannot add extension function to ${ctx.type().text}")
+ }
+ }
+ } else {
+ val clsStr = ctx.type().className().text.split(":")
+ val id: String
+ val nsp: String?
+ if (clsStr.size == 1) {
+ id = clsStr[0]
+ nsp = null
+ } else {
+ id = clsStr[1]
+ nsp = clsStr[0]
+ }
+ val owo: Class? = GlobalField.getClass(nsp, id)
+ if (owo == null) {
+ val pwp = GlobalField.getTemplate(nsp, id)
+ if (pwp == null) {
+ LogProcessor.error("Undefined class or struct:" + ctx.type().className().text)
+ f = UnknownFunction(ctx.Identifier().text)
+ Function.currFunction = f
+ return
+ } else {
+ pwp
+ }
+ } else {
+ owo
+ }
+ }
+ //解析参数
+ val types = FunctionParam.parseReadonlyAndNormalParamTypes(ctx.functionParams())
+ val field = if (ctx.STATIC() != null) data.staticField else data.field
+ //获取缓存中的对象
+ f = field.getFunction(ctx.Identifier().text, types.first, types.second)
+
+ Function.currFunction = f
+
+ for (a in annoInGlobal) {
+ a.forFunction(f)
+ }
+ annoInGlobal.clear()
+ }
+
+ fun exitExtensionFunctionDeclaration(ctx: mcfppParser.ExtensionFunctionDeclarationContext) {
+ Project.ctx = ctx
+ //函数是否有返回值
+ if (Function.currFunction.returnType != MCFPPBaseType.Void && !Function.currFunction.hasReturnStatement) {
+ LogProcessor.error("A 'return' expression required in function: " + Function.currFunction.namespaceID)
+ }
+ Function.currFunction = Function.nullFunction
+ }
+
+//region 逻辑语句
+
+ @InsertCommand
+ override fun visitReturnStatement(ctx: mcfppParser.ReturnStatementContext): Any? {
+ Project.ctx = ctx
+ Function.addCommand("#" + ctx.text)
+ if (ctx.expression() != null) {
+ val ret: Var<*> = McfppExprVisitor().visit(ctx.expression())!!
+ Function.currBaseFunction.assignReturnVar(ret)
+ }
+ if (Function.currFunction !is InternalFunction)
+ Function.currFunction.hasReturnStatement = true
+ Function.addCommand("return 1")
+ return null
+ }
+
+ override fun visitIfStatement(ctx: mcfppParser.IfStatementContext): Any? {
+ enterIfStatement(ctx)
+ super.visitIfStatement(ctx)
+ exitIfStatement(ctx)
+ return null
+ }
+
+ /**
+ * 进入if语句
+ * Enter if statement
+ *
+ * @param ctx
+ */
+
+ @InsertCommand
+ fun enterIfStatement(ctx: mcfppParser.IfStatementContext) {
+ //进入if函数
+ Project.ctx = ctx
+ Function.addCommand("#" + "if start")
+ val ifFunction = InternalFunction("_if_", Function.currFunction)
+ ifFunction.invoke(ArrayList(), null)
+ Function.currFunction = ifFunction
+ if (!GlobalField.localNamespaces.containsKey(ifFunction.namespace))
+ GlobalField.localNamespaces[ifFunction.namespace] = Namespace(ifFunction.namespace)
+ GlobalField.localNamespaces[ifFunction.namespace]!!.field.addFunction(ifFunction, false)
+ }
+
+ /**
+ * 离开if语句
+ * Exit if statement
+ *
+ * @param ctx
+ */
+ @InsertCommand
+ fun exitIfStatement(ctx: mcfppParser.IfStatementContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.currFunction.parent[0]
+ //调用完毕,将子函数的栈销毁
+ Function.addCommand("#" + "if end")
+ }
+
+ override fun visitIfBlock(ctx: mcfppParser.IfBlockContext): Any? {
+ enterIfBlock(ctx)
+ super.visitIfBlock(ctx)
+ exitIfBlock(ctx)
+ return null
+ }
+
+ /**
+ * 进入if分支的语句块
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun enterIfBlock(ctx: mcfppParser.IfBlockContext) {
+ Project.ctx = ctx
+ val parent = ctx.parent
+ Function.addCommand("#if branch start")
+ //匿名函数的定义
+ val f = InternalFunction("_if_branch_", Function.currFunction)
+ //注册函数
+ if (!GlobalField.localNamespaces.containsKey(f.namespace))
+ GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
+ GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f, false)
+ if (parent is mcfppParser.IfStatementContext || parent is mcfppParser.ElseIfStatementContext) {
+ //第一个if
+ parent as mcfppParser.IfStatementContext
+ val exp = McfppExprVisitor().visit(parent.expression())
+ if (exp !is MCBool) {
+ throw TypeCastException()
+ }
+ if (exp is MCBoolConcrete && exp.value) {
+ //函数调用的命令
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand("function " + f.namespaceID)
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.addCommand("return 1")
+ LogProcessor.warn("The condition is always true. ")
+ } else if (exp is MCBoolConcrete) {
+ Function.addCommand("#function " + f.namespaceID)
+ Function.addCommand("return 1")
+ LogProcessor.warn("The condition is always false. ")
+ } else {
+ exp as ReturnedMCBool
+ val exp1 = MCBool()
+ exp1.assign(exp)
+ //给子函数开栈
+ Function.addCommand(
+ "execute " +
+ "if score " + exp1.name + " " + SbObject.MCFPP_boolean + " matches 1 " +
+ "run data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}"
+ )
+ Function.addCommand(
+ "execute " +
+ "if score " + exp1.name + " " + SbObject.MCFPP_boolean + " matches 1 " +
+ "run function " + f.namespaceID
+ )
+ Function.addCommand(
+ "execute " +
+ "if score " + exp1.name + " " + SbObject.MCFPP_boolean + " matches 1 " +
+ "run data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]"
+ )
+ //由于下一个函数被直接中断,因此需要自己把自己的栈去掉
+ Function.addCommand(
+ "execute " +
+ "if score " + exp1.name + " " + SbObject.MCFPP_boolean + " matches 1 " +
+ "run data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]"
+ )
+ Function.addCommand(
+ "execute " +
+ "if score " + exp1.name + " " + SbObject.MCFPP_boolean + " matches 1 " +
+ "run return 1"
+ )
+ }
+ } else {
+ //else语句
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand("function " + f.namespaceID)
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ }
+ Function.currFunction = f
+ }
+
+ /**
+ * 离开if语句块
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun exitIfBlock(ctx: mcfppParser.IfBlockContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.currFunction.parent[0]
+ Function.addCommand("#if branch end")
+ }
+
+ override fun visitWhileStatement(ctx: mcfppParser.WhileStatementContext): Any? {
+ enterWhileStatement(ctx)
+ super.visitWhileStatement(ctx)
+ exitWhileStatement(ctx)
+ return null
+ }
+
+ @InsertCommand
+ fun enterWhileStatement(ctx: mcfppParser.WhileStatementContext) {
+ //进入if函数
+ Project.ctx = ctx
+ Function.addCommand("#while start")
+ val whileFunction = InternalFunction("_while_", Function.currFunction)
+ Function.addCommand("function " + whileFunction.namespaceID)
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.currFunction = whileFunction
+ if (!GlobalField.localNamespaces.containsKey(whileFunction.namespace))
+ GlobalField.localNamespaces[whileFunction.namespace] = Namespace(whileFunction.namespace)
+ GlobalField.localNamespaces[whileFunction.namespace]!!.field.addFunction(whileFunction, false)
+ }
+
+
+ @InsertCommand
+ fun exitWhileStatement(ctx: mcfppParser.WhileStatementContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.currFunction.parent[0]
+ //调用完毕,将子函数的栈销毁
+ Function.addCommand("#while end")
+ }
+
+
+ override fun visitWhileBlock(ctx: mcfppParser.WhileBlockContext): Any? {
+ enterWhileBlock(ctx)
+ super.visitWhileBlock(ctx)
+ exitWhileBlock(ctx)
+ return null
+ }
+
+ /**
+ * 进入while语句块
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun enterWhileBlock(ctx: mcfppParser.WhileBlockContext) {
+ Project.ctx = ctx
+ //入栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand("#" + "while start")
+ val parent: mcfppParser.WhileStatementContext = ctx.parent as mcfppParser.WhileStatementContext
+ val exp: MCBool = McfppExprVisitor().visit(parent.expression()) as MCBool
+ //匿名函数的定义
+ val f: Function = InternalFunction("_while_block_", Function.currFunction)
+ f.child.add(f)
+ f.parent.add(f)
+ if (!GlobalField.localNamespaces.containsKey(f.namespace))
+ GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
+ GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f, false)
+ //条件判断
+ if (exp is MCBoolConcrete && exp.value) {
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(
+ "execute " +
+ "if function " + f.namespaceID + " " +
+ "run function " + Function.currFunction.namespaceID
+ )
+ LogProcessor.warn("The condition is always true. ")
+ } else if (exp is MCBoolConcrete) {
+ //给子函数开栈
+ Function.addCommand("#function " + f.namespaceID)
+ LogProcessor.warn("The condition is always false. ")
+ } else {
+ exp as ReturnedMCBool
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ //函数返回1才会继续执行(continue或者正常循环完毕),返回0则不继续循环(break)
+ Function.addCommand(
+ "execute " +
+ "if function " + exp.parentFunction.namespaceID + " " +
+ "if function " + f.namespaceID + " " +
+ "run function " + Function.currFunction.namespaceID
+ )
+ }
+ Function.currFunction = f //后续块中的命令解析到递归的函数中
+
+ }
+
+ /**
+ * 离开while语句块
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun exitWhileBlock(ctx: mcfppParser.WhileBlockContext) {
+ Project.ctx = ctx
+ //调用完毕,将子函数的栈销毁
+ //由于在同一个命令中完成了两个函数的调用,因此需要在子函数内部进行子函数栈的销毁工作
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ //这里取出while函数的栈
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.addCommand("return 1")
+ Function.currFunction = Function.currFunction.parent[0]
+ Function.addCommand("#while loop end")
+ }
+
+ override fun visitDoWhileStatement(ctx: mcfppParser.DoWhileStatementContext): Any? {
+ enterDoWhileStatement(ctx)
+ super.visitDoWhileStatement(ctx)
+ exitDoWhileStatement(ctx)
+ return null
+ }
+
+ @InsertCommand
+ fun enterDoWhileStatement(ctx: mcfppParser.DoWhileStatementContext) {
+ //进入do-while函数
+ Project.ctx = ctx
+ Function.addCommand("#do-while start")
+ val doWhileFunction = InternalFunction("_dowhile_", Function.currFunction)
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand("function " + doWhileFunction.namespaceID)
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.currFunction = doWhileFunction
+ if (!GlobalField.localNamespaces.containsKey(doWhileFunction.namespace))
+ GlobalField.localNamespaces[doWhileFunction.namespace] = Namespace(doWhileFunction.namespace)
+ GlobalField.localNamespaces[doWhileFunction.namespace]!!.field.addFunction(doWhileFunction, false)
+ }
+
+
+ /**
+ * 离开do-while语句
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun exitDoWhileStatement(ctx: mcfppParser.DoWhileStatementContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.currFunction.parent[0]
+ //调用完毕,将子函数的栈销毁
+ Function.addCommand("#do-while end")
+ }
+
+
+ override fun visitDoWhileBlock(ctx: mcfppParser.DoWhileBlockContext): Any? {
+ enterDoWhileBlock(ctx)
+ super.visitDoWhileBlock(ctx)
+ exitDoWhileBlock(ctx)
+ return null
+ }
+
+ /**
+ * 进入do-while语句块,开始匿名函数调用
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun enterDoWhileBlock(ctx: mcfppParser.DoWhileBlockContext) {
+ Project.ctx = ctx
+ Function.addCommand("#do while start")
+ //匿名函数的定义
+ val f: Function = InternalFunction("_dowhile_", Function.currFunction)
+ f.child.add(f)
+ f.parent.add(f)
+ if (!GlobalField.localNamespaces.containsKey(f.namespace)) {
+ GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
+ }
+ GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f, false)
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(
+ "execute " +
+ "unless function " + f.namespaceID + " " +
+ "run return 1"
+ )
+ val parent = ctx.parent as mcfppParser.DoWhileStatementContext
+ val exp: MCBool = McfppExprVisitor().visit(parent.expression()) as MCBool
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ //递归调用
+ if (exp is MCBoolConcrete && exp.value) {
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(
+ "execute " +
+ "if function " + f.namespaceID + " " +
+ "run function " + Function.currFunction.namespaceID
+ )
+ LogProcessor.warn("The condition is always true. ")
+ } else if (exp is MCBoolConcrete) {
+ //给子函数开栈
+ Function.addCommand("#" + Commands.function(Function.currFunction))
+ LogProcessor.warn("The condition is always false. ")
+ } else {
+ exp as ReturnedMCBool
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(
+ "execute " +
+ "if function ${exp.parentFunction.namespaceID} " +
+ "run " + Commands.function(Function.currFunction)
+ )
+ }
+ Function.currFunction = f //后续块中的命令解析到递归的函数中
+ }
+
+
+ @InsertCommand
+ fun exitDoWhileBlock(ctx: mcfppParser.DoWhileBlockContext) {
+ Project.ctx = ctx
+ //调用完毕,将子函数的栈销毁
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ //调用完毕,将子函数的栈销毁
+ Function.currFunction = Function.currFunction.parent[0]
+ Function.addCommand("#do while end")
+ }
+
+
+ override fun visitForStatement(ctx: mcfppParser.ForStatementContext): Any? {
+ enterForStatement(ctx)
+ super.visitForStatement(ctx)
+ exitForStatement(ctx)
+ return null
+ }
+
+ /**
+ * 整个for语句本身额外有一个栈,无条件调用函数
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun enterForStatement(ctx: mcfppParser.ForStatementContext) {
+ Project.ctx = ctx
+ Function.addCommand("#for start")
+ val forFunc: Function = InternalFunction("_for_", Function.currFunction)
+ forFunc.parent.add(Function.currFunction)
+ if (!GlobalField.localNamespaces.containsKey(forFunc.namespace))
+ GlobalField.localNamespaces[forFunc.namespace] = Namespace(forFunc.identifier)
+ GlobalField.localNamespaces[forFunc.namespace]!!.field.addFunction(forFunc, false)
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(Commands.function(forFunc))
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.currFunction = forFunc
+ }
+
+
+ @InsertCommand
+ fun exitForStatement(ctx: mcfppParser.ForStatementContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.currFunction.parent[0]
+ Function.addCommand("#for end")
+ }
+
+ override fun visitForInit(ctx: mcfppParser.ForInitContext): Any? {
+ enterForInit(ctx)
+ super.visitForInit(ctx)
+ exitForInit(ctx)
+ return null
+ }
+
+ @InsertCommand
+ fun enterForInit(ctx: mcfppParser.ForInitContext) {
+ Project.ctx = ctx
+ Function.addCommand("#for init start")
+ }
+
+
+ @InsertCommand
+ fun exitForInit(ctx: mcfppParser.ForInitContext) {
+ Project.ctx = ctx
+ Function.addCommand("#for init end")
+ //进入for循环主体
+ Function.addCommand("#for loop start")
+ val forLoopFunc: Function = InternalFunction("_for_loop_", Function.currFunction)
+ forLoopFunc.parent.add(Function.currFunction)
+ if (!GlobalField.localNamespaces.containsKey(forLoopFunc.namespace))
+ GlobalField.localNamespaces[forLoopFunc.namespace] = Namespace(forLoopFunc.identifier)
+ GlobalField.localNamespaces[forLoopFunc.namespace]!!.field.addFunction(forLoopFunc, false)
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(Commands.function(forLoopFunc))
+
+ }
+
+
+ /**
+ * 进入for update语句块。
+ * 由于在编译过程中,编译器会首先编译for语句的for control部分,也就是for后面的括号,这就意味着forUpdate语句将会先forBlock
+ * 被写入到命令函数中。因此我们需要将forUpdate语句中的命令临时放在一个列表内部,然后在forBlock调用完毕后加上它的命令
+ *
+ * @param ctx the parse tree
+ */
+
+ override fun visitForUpdate(ctx: mcfppParser.ForUpdateContext): Any? {
+ enterForUpdate(ctx)
+ super.visitForUpdate(ctx)
+ exitForUpdate(ctx)
+ return null
+ }
+
+ fun enterForUpdate(ctx: mcfppParser.ForUpdateContext) {
+ Project.ctx = ctx
+ forInitCommands = Function.currFunction.commands
+ Function.currFunction.commands = forUpdateCommands
+ }
+
+ //暂存
+ private var forInitCommands = CommandList()
+ private var forUpdateCommands = CommandList()
+
+ /**
+ * 离开for update。暂存for update缓存,恢复主缓存,准备forblock编译
+ * @param ctx the parse tree
+ */
+
+ fun exitForUpdate(ctx: mcfppParser.ForUpdateContext) {
+ Project.ctx = ctx
+ Function.currFunction.commands = forInitCommands
+ }
+
+ override fun visitForBlock(ctx: mcfppParser.ForBlockContext): Any? {
+ enterForBlock(ctx)
+ super.visitForBlock(ctx)
+ exitForBlock(ctx)
+ return null
+ }
+
+ /**
+ * 进入for block语句。此时当前函数为父函数
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun enterForBlock(ctx: mcfppParser.ForBlockContext) {
+ Project.ctx = ctx
+ val parent: mcfppParser.ForStatementContext = ctx.parent as mcfppParser.ForStatementContext
+ val exp: MCBool = McfppExprVisitor().visit(parent.forControl().expression()) as MCBool
+ //匿名函数的定义。这里才是正式的for函数哦喵
+ val f: Function = InternalFunction("_forblock_", Function.currFunction)
+ f.child.add(f)
+ f.parent.add(f)
+ if (!GlobalField.localNamespaces.containsKey(f.namespace))
+ GlobalField.localNamespaces[f.namespace] = Namespace(f.namespace)
+ GlobalField.localNamespaces[f.namespace]!!.field.addFunction(f, false)
+ //条件循环判断
+ if (exp is MCBoolConcrete && exp.value) {
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ Function.addCommand(
+ "execute " +
+ "if function " + f.namespaceID + " " +
+ "run function " + Function.currFunction.namespaceID
+ )
+ LogProcessor.warn("The condition is always true. ")
+ } else if (exp is MCBoolConcrete) {
+ //给子函数开栈
+ Function.addCommand("#function " + f.namespaceID)
+ LogProcessor.warn("The condition is always false. ")
+ } else {
+ exp as ReturnedMCBool
+ //给子函数开栈
+ Function.addCommand("data modify storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame prepend value {}")
+ //函数返回1才会继续执行(continue或者正常循环完毕),返回0则不继续循环(break)
+ Function.addCommand(
+ "execute " +
+ "if function ${exp.parentFunction.namespaceID} " +
+ "if function " + f.namespaceID + " " +
+ "run function " + Function.currFunction.namespaceID
+ )
+ }
+ //调用完毕,将子函数的栈销毁。这条命令仍然是在for函数中的。
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.currFunction = f //后续块中的命令解析到递归的函数中
+ }
+
+ /**
+ * 离开for block语句。此时当前函数仍然是for的函数
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ fun exitForBlock(ctx: mcfppParser.ForBlockContext) {
+ Project.ctx = ctx
+ //for-update的命令压入
+ Function.currFunction.commands.addAll(forUpdateCommands)
+ forUpdateCommands.clear()
+ //调用完毕,将子函数的栈销毁
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ //继续销毁for-loop函数的栈
+ Function.addCommand("data remove storage mcfpp:system " + Project.config.defaultNamespace + ".stack_frame[0]")
+ Function.currFunction = Function.currFunction.parent[0]
+ }
+//endregion
+
+
+ @InsertCommand
+ override fun visitOrgCommand(ctx: mcfppParser.OrgCommandContext): Any? {
+ Project.ctx = ctx
+ Function.addCommand(ctx.text.substring(1))
+ return null
+ }
+
+ /**
+ * 进入任意语句,检查此函数是否还能继续添加语句
+ * @param ctx the parse tree
+ */
+
+ @InsertCommand
+ override fun visitStatement(ctx: mcfppParser.StatementContext): Any? {
+ Project.ctx = ctx
+ if (Function.currFunction.isEnd) {
+ LogProcessor.warn("Unreachable code: " + ctx.text)
+ }
+ super.visitStatement(ctx)
+ return null
+ }
+
+ private var temp: MCBool? = null
+
+ @InsertCommand
+ override fun visitControlStatement(ctx: mcfppParser.ControlStatementContext): Any? {
+ Project.ctx = ctx
+ if (!inLoopStatement(ctx)) {
+ LogProcessor.error("'continue' or 'break' can only be used in loop statements.")
+ return null
+ }
+ Function.addCommand("#" + ctx.text)
+ //return语句
+ if (ctx.BREAK() != null) {
+ Function.addCommand("return 0")
+ } else {
+ Function.addCommand("return 1")
+ }
+ Function.currFunction.isEnd = true
+ return null
+ }
+
+ //region class
+
+ /**
+ * 注解
+ *
+ * @param ctx
+ */
+ //TODO: Func
+ override fun visitClassAnnotation(ctx: mcfppParser.ClassAnnotationContext): Any? {
+ Project.ctx = ctx
+ val anno = GlobalField.annotations[ctx.id.text]
+ if (anno == null) {
+ LogProcessor.error("Annotation ${ctx.id.text} not found")
+ return null
+ }
+ //参数获取
+ val normalArgs: ArrayList> = ArrayList()
+ val readOnlyParams: ArrayList> = ArrayList()
+ val exprVisitor = McfppExprVisitor()
+ ctx.arguments().readOnlyArgs()?.let {
+ for (expr in it.expressionList().expression()) {
+ val arg = exprVisitor.visit(expr)!!
+ readOnlyParams.add(arg)
+ }
+ }
+ for (expr in ctx.arguments().normalArgs().expressionList().expression()) {
+ val arg = exprVisitor.visit(expr)!!
+ normalArgs.add(arg)
+ }
+ if (Class.currClass == null && Template.currTemplate == null) {
+ //在全局
+ annoInGlobal.add(Annotation.newInstance(anno, normalArgs))
+ } else {
+ annoInCompound.add(Annotation.newInstance(anno, normalArgs))
+ }
+ return null
+ }
+
+ override fun visitClassDeclaration(ctx: mcfppParser.ClassDeclarationContext): Any? {
+ if (ctx.readOnlyParams() == null) {
+ super.visitClassDeclaration(ctx)
+ }
+ return null
+ }
+
+ override fun visitClassBody(ctx: mcfppParser.ClassBodyContext): Any? {
+ enterClassBody(ctx)
+ super.visitClassBody(ctx)
+ exitClassBody(ctx)
+ return null
+ }
+
+ /**
+ * 进入类体。
+ * @param ctx the parse tree
+ */
+ private fun enterClassBody(ctx: mcfppParser.ClassBodyContext) {
+ Project.ctx = ctx
+ //获取类的对象
+ val parent: mcfppParser.ClassDeclarationContext = ctx.parent as mcfppParser.ClassDeclarationContext
+ val identifier: String = parent.classWithoutNamespace().text
+ //设置作用域
+ Class.currClass = GlobalField.getClass(Project.currNamespace, identifier)
+ Function.currFunction = Class.currClass!!.classPreInit
+ //注解
+ for (a in annoInGlobal) {
+ a.forClass(Class.currClass!!)
+ }
+ annoInGlobal.clear()
+ }
+
+ /**
+ * 离开类体。将缓存重新指向全局
+ * @param ctx the parse tree
+ */
+
+ private fun exitClassBody(ctx: mcfppParser.ClassBodyContext) {
+ Project.ctx = ctx
+ Class.currClass = null
+ Function.currFunction = Function.nullFunction
+ }
+
+ /**
+ * 类成员的声明
+ * @param ctx the parse tree
+ */
+
+ override fun visitClassMemberDeclaration(ctx: mcfppParser.ClassMemberDeclarationContext): Any? {
+ Project.ctx = ctx
+ val memberContext: mcfppParser.ClassMemberContext = ctx.classMember() ?: return null
+ if (memberContext.classFunctionDeclaration() != null) {
+ //函数声明由函数的listener处理
+ visit(memberContext.classFunctionDeclaration())
+ return null
+ }
+ return null
+ }
+
+ override fun visitClassFunctionDeclaration(ctx: mcfppParser.ClassFunctionDeclarationContext): Any? {
+ //是类的成员函数
+ enterClassFunctionDeclaration(ctx)
+ super.visitClassFunctionDeclaration(ctx)
+ exitClassFunctionDeclaration(ctx)
+ return null
+ }
+
+ fun enterClassFunctionDeclaration(ctx: mcfppParser.ClassFunctionDeclarationContext) {
+ Project.ctx = ctx
+ //解析参数
+ val types = FunctionParam.parseReadonlyAndNormalParamTypes(ctx.functionParams())
+ //获取缓存中的对象
+ val fun1 = Class.currClass!!.field.getFunction(ctx.Identifier().text, types.first, types.second)
+ val f = if (fun1 is UnknownFunction) Class.currClass!!.staticField.getFunction(
+ ctx.Identifier().text,
+ types.first,
+ types.second
+ ) else fun1
+ Function.currFunction = f
+
+ //对函数进行注解处理
+ for (a in annoInCompound) {
+ a.forFunction(f)
+ }
+ annoInCompound.clear()
+ }
+
+ fun exitClassFunctionDeclaration(ctx: mcfppParser.ClassFunctionDeclarationContext) {
+ Project.ctx = ctx
+ Function.currFunction = Class.currClass!!.classPreInit
+ }
+
+ override fun visitConstructorDeclaration(ctx: mcfppParser.ConstructorDeclarationContext): Any? {
+ //是构造函数
+ enterConstructorDeclaration(ctx)
+ super.visitConstructorDeclaration(ctx)
+ exitConstructorDeclaration(ctx)
+ return null
+ }
+
+ fun enterConstructorDeclaration(ctx: mcfppParser.ConstructorDeclarationContext) {
+ Project.ctx = ctx
+ val types = FunctionParam.parseNormalParamTypes(ctx.normalParams())
+ val c = Class.currClass!!.getConstructor(types.typeToStringList())!!
+ Function.currFunction = c
+ //注解
+ for (a in annoInCompound) {
+ a.forFunction(c)
+ }
+ annoInCompound.clear()
+ }
+
+ fun exitConstructorDeclaration(ctx: mcfppParser.ConstructorDeclarationContext) {
+ Project.ctx = ctx
+ Function.currFunction = Class.currClass!!.classPreInit
+ }
+ //endregion
+
+ //region struct
+
+ /**
+ * 进入类体。
+ * @param ctx the parse tree
+ */
+
+ override fun visitTemplateBody(ctx: mcfppParser.TemplateBodyContext): Any? {
+ enterTemplateBody(ctx)
+ super.visitTemplateBody(ctx)
+ exitTemplateBody(ctx)
+ return null
+ }
+
+ fun enterTemplateBody(ctx: mcfppParser.TemplateBodyContext) {
+ Project.ctx = ctx
+ //获取类的对象
+ val parent = ctx.parent as mcfppParser.TemplateDeclarationContext
+ val identifier: String = parent.classWithoutNamespace().text
+ //设置作用域
+ Template.currTemplate = GlobalField.getTemplate(Project.currNamespace, identifier)
+ }
+
+ /**
+ * 离开类体。将缓存重新指向全局
+ * @param ctx the parse tree
+ */
+
+ fun exitTemplateBody(ctx: mcfppParser.TemplateBodyContext) {
+ Project.ctx = ctx
+ Template.currTemplate = null
+ }
+
+ override fun visitTemplateFunctionDeclaration(ctx: mcfppParser.TemplateFunctionDeclarationContext): Any? {
+ enterTemplateFunctionDeclaration(ctx)
+ super.visitTemplateFunctionDeclaration(ctx)
+ exitTemplateFunctionDeclaration(ctx)
+ return null
+ }
+
+ fun enterTemplateFunctionDeclaration(ctx: mcfppParser.TemplateFunctionDeclarationContext) {
+ Project.ctx = ctx
+ //解析参数
+ val types = FunctionParam.parseReadonlyAndNormalParamTypes(ctx.functionParams())
+ //获取缓存中的对象
+ val fun1 = Template.currTemplate!!.field.getFunction(ctx.Identifier().text, types.first, types.second)
+ val f = if (fun1 is UnknownFunction) Template.currTemplate!!.staticField.getFunction(
+ ctx.Identifier().text,
+ types.first,
+ types.second
+ ) else fun1
+ Function.currFunction = f
+
+ //对函数进行注解处理
+ for (a in annoInCompound) {
+ a.forFunction(f)
+ }
+ annoInCompound.clear()
+ }
+
+ fun exitTemplateFunctionDeclaration(ctx: mcfppParser.TemplateFunctionDeclarationContext) {
+ Project.ctx = ctx
+ Function.currFunction = Function.nullFunction
+ }
+
+ //endregion
+
+ companion object {
+ /**
+ * 判断这个语句是否在循环语句中。包括嵌套形式。
+ * @param ctx 需要判断的语句
+ * @return 是否在嵌套中
+ */
+ private fun inLoopStatement(ctx: RuleContext): Boolean {
+ if (ctx is mcfppParser.ForStatementContext) {
+ return true
+ }
+ if (ctx is mcfppParser.DoWhileStatementContext) {
+ return true
+ }
+ if (ctx is mcfppParser.WhileStatementContext) {
+ return true
+ }
+ return if (ctx.parent != null) {
+ inLoopStatement(ctx.parent)
+ } else false
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppInlineFunctionVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppInlineFunctionVisitor.kt
new file mode 100644
index 00000000..ba645932
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppInlineFunctionVisitor.kt
@@ -0,0 +1,3 @@
+package top.mcfpp.antlr
+
+class McfppInlineFunctionVisitor : McfppImVisitor()
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppLeftExprVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppLeftExprVisitor.kt
new file mode 100644
index 00000000..f5a54f9b
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppLeftExprVisitor.kt
@@ -0,0 +1,237 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.Project
+import top.mcfpp.annotations.InsertCommand
+import top.mcfpp.lang.*
+import top.mcfpp.model.Class
+import top.mcfpp.model.Member
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.function.ExtensionFunction
+import top.mcfpp.model.function.Function
+import top.mcfpp.model.function.FunctionParam
+import top.mcfpp.model.function.UnknownFunction
+import top.mcfpp.model.generic.Generic
+import top.mcfpp.model.generic.GenericClass
+import top.mcfpp.util.LogProcessor
+import top.mcfpp.util.StringHelper
+import java.util.*
+
+class McfppLeftExprVisitor : mcfppParserBaseVisitor?>() {
+ private var currSelector: CanSelectMember? = null
+
+ /**
+ * 计算一个基本的表达式。可能是一个变量,也可能是一个数值
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitBasicExpression(ctx: mcfppParser.BasicExpressionContext): Var<*>? {
+ Project.ctx = ctx
+ return if (ctx.primary() != null) {
+ visit(ctx.primary())
+ } else {
+ visit(ctx.varWithSelector())
+ }
+ }
+
+ /**
+ * 从类中选择一个成员。返回的成员包含了它所在的对象的信息
+ *
+ * @param ctx
+ * @return
+ */
+ @Override
+ override fun visitVarWithSelector(ctx: mcfppParser.VarWithSelectorContext): Var<*>? {
+ Project.ctx = ctx
+ currSelector = if (ctx.primary() != null) {
+ visit(ctx.primary())
+ } else {
+ if (ctx.type().className() != null) {
+ //ClassName
+ val clsstr = StringHelper.splitNamespaceID(ctx.type().text)
+ val qwq: Class? = GlobalField.getClass(clsstr.first, clsstr.second)
+ if (qwq == null) {
+ LogProcessor.error("Undefined class:" + ctx.type().className().text)
+ return UnknownVar("${ctx.type().className().text}_type_" + UUID.randomUUID())
+ }
+ qwq.getType()
+ } else {
+ CompoundDataType(
+ //基本类型
+ when (ctx.type().text) {
+ "int" -> MCInt.data
+ else -> TODO()
+ }
+ )
+ }
+ }
+ for (selector in ctx.selector().subList(0, ctx.selector().size - 1)) {
+ visit(selector)
+ }
+ return visit(ctx.selector(ctx.selector().size - 1).`var`())
+ }
+
+ @Override
+ override fun visitSelector(ctx: mcfppParser.SelectorContext?): Var<*>? {
+ currSelector = visit(ctx!!.`var`())!!.getTempVar()
+ return null
+ }
+
+ /**
+ * 一个初级表达式,可能是一个变量,也可能是一个数值
+ * @param ctx the parse tree
+ * @return 表达式的值
+ */
+ @Override
+ override fun visitPrimary(ctx: mcfppParser.PrimaryContext): Var<*>? {
+ Project.ctx = ctx
+ if (ctx.`var`() != null) {
+ //变量
+ return visit(ctx.`var`())
+ } else if (ctx.value() != null) {
+ //数字
+ val num: mcfppParser.ValueContext = ctx.value()
+ if (num.intValue() != null) {
+ return MCIntConcrete(Integer.parseInt(num.intValue().text))
+ } else if (num.LineString() != null) {
+ val r: String = num.LineString().text
+ return MCString(r.substring(1, r.length - 1))
+ }
+ } else {
+ //this或者super
+ val s = if (ctx.SUPER() != null) {
+ "super"
+ } else {
+ "this"
+ }
+ val re: Var<*>? = Function.field.getVar(s)
+ if (re == null) {
+ LogProcessor.error("$s can only be used in member functions.")
+ }
+ return re
+ }
+ return null
+ }
+
+ /**
+ * 变量
+ * @param ctx the parse tree
+ * @return 变量
+ */
+ @Override
+ @InsertCommand
+ override fun visitVar(ctx: mcfppParser.VarContext): Var<*>? {
+ Project.ctx = ctx
+ return if (ctx.Identifier() != null && ctx.arguments() == null) {
+ // Identifier identifierSuffix*
+ if (ctx.identifierSuffix() == null || ctx.identifierSuffix().size == 0) {
+ //没有数组选取
+ val qwq: String = ctx.Identifier().text
+ if (currSelector == null) {
+ val re: Var<*>? = Function.field.getVar(qwq)
+ if (re == null) {
+ LogProcessor.error("Undefined variable:$qwq")
+ }
+ re
+ } else {
+ val cpd = when (currSelector) {
+ is CompoundDataType -> (currSelector as CompoundDataType).dataType
+ is ClassPointer -> (currSelector as ClassPointer).clsType
+ else -> TODO()
+ }
+ val am =
+ if (Function.currFunction !is ExtensionFunction && Function.currFunction.ownerType == Function.Companion.OwnerType.CLASS) {
+ Function.currFunction.parentClass()!!.getAccess(cpd)
+ } else if (Function.currFunction !is ExtensionFunction && Function.currFunction.ownerType == Function.Companion.OwnerType.TEMPLATE) {
+ Function.currFunction.parentStruct()!!.getAccess(cpd)
+ } else {
+ Member.AccessModifier.PUBLIC
+ }
+ val re = currSelector!!.getMemberVar(qwq, am)
+ if (re.first == null) {
+ LogProcessor.error("Undefined variable:$qwq")
+ }
+ if (!re.second) {
+ LogProcessor.error("Cannot access member $qwq")
+ }
+ re.first
+ }
+ } else {
+ TODO("数组调用")
+ }
+ } else if (ctx.expression() != null) {
+ // '(' expression ')'
+ visit(ctx.expression())
+ } else {
+ //函数的调用
+ Function.addCommand("#" + ctx.text)
+ //参数获取
+ val normalArgs: ArrayList> = ArrayList()
+ val readOnlyArgs: ArrayList> = ArrayList()
+ val exprVisitor = McfppExprVisitor()
+ for (expr in ctx.arguments().readOnlyArgs()?.expressionList()?.expression() ?: emptyList()) {
+ val arg = exprVisitor.visit(expr)!!
+ readOnlyArgs.add(arg)
+ }
+ for (expr in ctx.arguments().normalArgs().expressionList()?.expression() ?: emptyList()) {
+ val arg = exprVisitor.visit(expr)!!
+ normalArgs.add(arg)
+ }
+ //获取函数
+ val p = StringHelper.splitNamespaceID(ctx.namespaceID().text)
+ val func = if (currSelector == null) {
+ GlobalField.getFunction(
+ p.first,
+ p.second,
+ FunctionParam.getArgTypeNames(readOnlyArgs),
+ FunctionParam.getArgTypeNames(normalArgs)
+ )
+ } else {
+ if (p.first != null) {
+ LogProcessor.warn("Invalid namespace usage ${p.first} in function call ")
+ }
+ McfppFuncManager().getFunction(
+ currSelector!!, p.second,
+ FunctionParam.getArgTypes(readOnlyArgs),
+ FunctionParam.getArgTypes(normalArgs)
+ )
+ }
+ //调用函数
+ return if (func is UnknownFunction) {
+ //可能是构造函数
+ var cls: Class? = GlobalField.getClass(p.first, p.second)
+ if (cls == null) {
+ LogProcessor.error("Function " + ctx.text + " not defined")
+ Function.addCommand("[Failed to Compile]${ctx.text}")
+ func.invoke(normalArgs, currSelector)
+ return func.returnVar
+ }
+ if (cls is GenericClass) {
+ //实例化泛型函数
+ cls = cls.compile(readOnlyArgs)
+ }
+ //获取对象
+ val ptr = cls.newInstance()
+ //调用构造函数
+ val constructor = cls.getConstructor(FunctionParam.getArgTypeNames(normalArgs))
+ if (constructor == null) {
+ LogProcessor.error("No constructor like: " + FunctionParam.getArgTypeNames(normalArgs) + " defined in class " + ctx.namespaceID().text)
+ Function.addCommand("[Failed to compile]${ctx.text}")
+ } else {
+ constructor.invoke(normalArgs, callerClassP = ptr)
+ }
+ return ptr
+ } else {
+ if (func is Generic<*>) {
+ func.invoke(readOnlyArgs, normalArgs, currSelector)
+ } else {
+ func.invoke(normalArgs, currSelector)
+ }
+ //函数树
+ Function.currFunction.child.add(func)
+ func.parent.add(Function.currFunction)
+ func.returnVar
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/McfppTypeVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/McfppTypeVisitor.kt
new file mode 100644
index 00000000..ef34773e
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/McfppTypeVisitor.kt
@@ -0,0 +1,259 @@
+package top.mcfpp.antlr
+
+import top.mcfpp.Project
+import top.mcfpp.io.MCFPPFile
+import top.mcfpp.lang.MCAny
+import top.mcfpp.lang.type.MCFPPType
+import top.mcfpp.model.*
+import top.mcfpp.model.field.GlobalField
+import top.mcfpp.model.generic.ClassParam
+import top.mcfpp.model.generic.GenericClass
+import top.mcfpp.util.LazyWrapper
+import top.mcfpp.util.LogProcessor
+import top.mcfpp.util.StringHelper
+
+/**
+ * 解析当前项目的类型
+ */
+class McfppTypeVisitor : mcfppParserBaseVisitor() {
+
+ /**
+ * 遍历整个文件。一个文件包含了命名空间的声明,函数的声明,类的声明以及全局变量的声明。全局变量是可以跨文件调用的。
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitCompilationUnit(ctx: mcfppParser.CompilationUnitContext) {
+ Project.ctx = ctx
+ //命名空间
+ if (ctx.namespaceDeclaration() != null) {
+ //获取命名空间
+ var namespaceStr = ctx.namespaceDeclaration().Identifier()[0].text
+ if (ctx.namespaceDeclaration().Identifier().size > 1) {
+ ctx.namespaceDeclaration().Identifier().forEach { e ->
+ run {
+ namespaceStr += ".${e.text}"
+ }
+ }
+ }
+ Project.currNamespace = namespaceStr
+ } else {
+ Project.currNamespace = Project.config.defaultNamespace
+ }
+ //导入库
+ for (lib in ctx.importDeclaration()) {
+ visit(lib)
+ }
+ if (!GlobalField.localNamespaces.containsKey(Project.currNamespace)) {
+ GlobalField.localNamespaces[Project.currNamespace] = Namespace(Project.currNamespace)
+ }
+ //文件结构,类和函数
+ for (t in ctx.typeDeclaration()) {
+ visit(t)
+ }
+ }
+
+ /**
+ * 完成一次库的import
+ * TODO 类型别名
+ *
+ * @param ctx
+ */
+ override fun visitImportDeclaration(ctx: mcfppParser.ImportDeclarationContext) {
+ Project.ctx = ctx
+ //获取命名空间
+ var namespace = ctx.Identifier(0).text
+ if (ctx.Identifier().size > 1) {
+ for (n in ctx.Identifier().subList(1, ctx.Identifier().size)) {
+ namespace += ".$n"
+ }
+ }
+ //获取库的命名空间
+ val libNamespace = GlobalField.libNamespaces[namespace]
+ if (libNamespace == null) {
+ LogProcessor.error("Namespace $namespace not found")
+ return
+ }
+ //将库的命名空间加入到importedLibNamespaces中
+ val nsp = Namespace(namespace)
+ GlobalField.importedLibNamespaces[namespace] = nsp
+
+ //这个库被引用的类
+ if (ctx.cls == null) {
+ //只导入方法
+ libNamespace.field.forEachFunction { f ->
+ run {
+ nsp.field.addFunction(f, false)
+ }
+ }
+ return
+ }
+ //导入类和方法
+ if (ctx.cls.text == "*") {
+ //全部导入
+ libNamespace.field.forEachClass { c ->
+ run {
+ nsp.field.addClass(c.identifier, c)
+ }
+ }
+ libNamespace.field.forEachFunction { f ->
+ run {
+ nsp.field.addFunction(f, false)
+ }
+ }
+ } else {
+ //只导入声明的类
+ val cls = libNamespace.field.getClass(ctx.cls.text)
+ if (cls != null) {
+ nsp.field.addClass(cls.identifier, cls)
+ } else {
+ LogProcessor.error("Class ${ctx.cls.text} not found in namespace $namespace")
+ }
+ }
+ }
+
+ /**
+ * 类或函数声明
+ *
+ * `classOrFunctionDeclaration
+ * : classDeclaration
+ * | functionDeclaration
+ * | nativeDeclaration
+ * ;`
+
*
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitDeclarations(ctx: mcfppParser.DeclarationsContext) {
+ Project.ctx = ctx
+ if (ctx.globalDeclaration() != null) return
+ super.visitDeclarations(ctx)
+ }
+
+ override fun visitInterfaceDeclaration(ctx: mcfppParser.InterfaceDeclarationContext) {
+ Project.ctx = ctx
+ //注册类
+ val id = ctx.classWithoutNamespace().text
+ val nsp = GlobalField.localNamespaces[Project.currNamespace]!!
+ if (nsp.field.hasInterface(id)) {
+ //重复声明
+ LogProcessor.error("Interface has been defined: $id in namespace ${Project.currNamespace}")
+ Interface.currInterface = nsp.field.getInterface(id)
+ } else {
+ //如果没有声明过这个类
+ val itf = Interface(id, Project.currNamespace)
+ for (p in ctx.className()) {
+ //是否存在继承
+ val nsn = StringHelper.splitNamespaceID(p.text)
+ val namespace = nsn.first
+ val identifier = nsn.second
+ val pc = GlobalField.getInterface(namespace, identifier)
+ if (pc == null) {
+ LogProcessor.error("Undefined Interface: " + p.text)
+ } else {
+ itf.parent.add(pc)
+ }
+ }
+ nsp.field.addInterface(id, itf)
+ }
+ }
+
+ /**
+ * TODO native类的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitNativeClassDeclaration(ctx: mcfppParser.NativeClassDeclarationContext) {
+ //NativeClassVisitor().visit(ctx)
+ }
+
+
+ /**
+ * 类的声明
+ * @param ctx the parse tree
+ * @return null
+ */
+ override fun visitClassDeclaration(ctx: mcfppParser.ClassDeclarationContext) {
+ Project.ctx = ctx
+ //注册类
+ val id = ctx.classWithoutNamespace().text
+ val nsp = GlobalField.localNamespaces[Project.currNamespace]!!
+
+ val cls = if (ctx.readOnlyParams() != null) {
+ //泛型类
+ val qwq = GenericClass(id, Project.currNamespace, ctx.classBody())
+ qwq.readOnlyParams.addAll(ctx.readOnlyParams().parameterList().parameter().map {
+ ClassParam(it.type().text, it.Identifier().text)
+ })
+ qwq
+ } else {
+ //如果没有声明过这个类
+ Class(id, Project.currNamespace)
+ }
+ if (!nsp.field.addClass(id, cls)) {
+ LogProcessor.error("Class has been defined: $id in namespace ${Project.currNamespace}")
+ return
+ }
+ cls.initialize()
+ if (ctx.className().size != 0) {
+ for (p in ctx.className()) {
+ //是否存在继承
+ val qwq = StringHelper.splitNamespaceID(p.text)
+ val identifier: String = qwq.second
+ val namespace: String? = qwq.first
+ var pc: CompoundData? = GlobalField.getClass(namespace, identifier)
+ if (pc == null) {
+ pc = GlobalField.getInterface(namespace, identifier)
+ if (pc == null) {
+ pc = Class.Companion.UndefinedClassOrInterface(identifier, namespace)
+ }
+ }
+ cls.extends(pc)
+ }
+ } else {
+ //继承Any类
+ cls.extends(MCAny.data)
+ }
+ cls.isStaticClass = ctx.STATIC() != null
+ cls.isAbstract = ctx.ABSTRACT() != null
+ }
+
+ /**
+ *
+ */
+ override fun visitTemplateDeclaration(ctx: mcfppParser.TemplateDeclarationContext?) {
+ Project.ctx = ctx!!
+ //注册模板
+ val id = ctx.classWithoutNamespace().text
+ val nsp = GlobalField.localNamespaces[Project.currNamespace]!!
+ if (nsp.field.hasTemplate(id)) {
+ //重复声明
+ LogProcessor.error("Template has been defined: $id in namespace ${Project.currNamespace}")
+ Template.currTemplate = nsp.field.getTemplate(id)
+ }
+ val template = Template(
+ id,
+ LazyWrapper { MCFPPType.parseFromIdentifier(ctx.type().text, MCFPPFile.currFile!!.field) },
+ Project.currNamespace
+ )
+ if (ctx.className() != null) {
+ //是否存在继承
+ val qwq = ctx.className().text.split(":")
+ val identifier: String
+ val namespace: String?
+ if (qwq.size == 1) {
+ identifier = qwq[0]
+ namespace = null
+ } else {
+ namespace = qwq[0]
+ identifier = qwq[1]
+ }
+ val s = GlobalField.getTemplate(namespace, identifier)
+ if (s == null) {
+ LogProcessor.error("Undefined template: " + ctx.className().text)
+ } else {
+ template.parent.add(s)
+ }
+ }
+ nsp.field.addTemplate(id, template)
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/antlr/NativeClassVisitor.kt b/src/main/kotlin/top/mcfpp/antlr/NativeClassVisitor.kt
new file mode 100644
index 00000000..4b55e6d8
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/antlr/NativeClassVisitor.kt
@@ -0,0 +1,78 @@
+package top.mcfpp.antlr
+
+/**
+ * 遍历一个Native类,并将其和java方法对应
+ *
+ * @constructor Create empty Native class visitor
+ */
+class NativeClassVisitor : mcfppParserBaseVisitor() {
+
+ /*
+ @Override
+ override fun visitNativeClassDeclaration(ctx: mcfppParser.NativeClassDeclarationContext?): Any? {
+ Project.ctx = ctx
+ //注册类
+ val identifier: String = ctx!!.classWithoutNamespace().text
+ if (GlobalField.localNamespaces[Project.currNamespace]!!.hasClass(identifier)) {
+ //重复声明
+ LogProcessor.error("Already defined class: $identifier")
+ throw ClassDuplicationException()
+ } else {
+ //获取它指向的java类
+ val cls: java.lang.Class = try {
+ java.lang.Class.forName(ctx.javaRefer().text) as java.lang.Class
+ } catch (e: ClassNotFoundException) {
+ throw RuntimeException(e)
+ } catch (e: ClassCastException) {
+ throw RuntimeException(e)
+ }
+ val ncls = NativeClass(identifier, cls)
+ GlobalField.localNamespaces[Project.currNamespace]!!.addClass(identifier, ncls)
+ Class.currClass = ncls
+ if(ctx.nativeClassBody() != null){
+ visit(ctx.nativeClassBody())
+ }
+ Class.currClass = null
+ }
+ return null
+ }
+
+ @Override
+ override fun visitNativeClassBody(ctx: mcfppParser.NativeClassBodyContext?): Any? {
+ ctx!!
+ for (i in ctx.nativeClassFunctionDeclaration()) {
+ val nf = visit(i) as NativeFunction?
+ if(nf != null){
+ Class.currClass!!.staticField.addFunction(nf,false)
+ }
+ }
+ return null
+ }
+
+ @Override
+ override fun visitNativeClassFunctionDeclaration(ctx: mcfppParser.NativeClassFunctionDeclarationContext?): Any? {
+ //accessModifier? NATIVE 'func' Identifier '(' parameterList? ')' ';'
+ ctx!!
+ val accessModifier: Member.AccessModifier = if (ctx.accessModifier() != null) {
+ Member.AccessModifier.valueOf(ctx.accessModifier().text.lowercase())
+ } else {
+ Member.AccessModifier.PUBLIC
+ }
+ //获取这个java方法
+ val javaMethod : Method
+ try{
+ val cls: java.lang.Class<*> = (Class.currClass as NativeClass).cls
+ javaMethod = cls.getMethod(ctx.Identifier().text , Array::class.java, ClassPointer::class.java)
+ } catch (e: NoSuchMethodException) {
+ LogProcessor.error("No such method:" + ctx.Identifier().text)
+ return null
+ }
+ val nf = NativeFunction(ctx.Identifier().text, javaMethod)
+ nf.accessModifier = accessModifier
+ if (ctx.parameterList() != null) {
+ nf.addParams(ctx.parameterList())
+ }
+ return nf
+ }
+ */
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/command/Command.kt b/src/main/kotlin/top/mcfpp/command/Command.kt
new file mode 100644
index 00000000..4a7595a9
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/command/Command.kt
@@ -0,0 +1,179 @@
+package top.mcfpp.command
+
+import top.mcfpp.exception.CommandException
+
+/**
+ * 一条编译时动态命令。包含了可以被替换的字符串位点,每个位点都有一个唯一的ID。
+ *
+ * @constructor Create empty Command
+ */
+open class Command {
+
+ protected val commandStringList = ArrayList()
+
+ private val tags = ArrayList()
+
+ private val replacePoint = HashMap()
+
+ var isCompleted = false
+
+ constructor(command: String) {
+ commandStringList.add(command)
+ }
+
+ constructor(command: String, pointID: String) {
+ replacePoint[pointID] = commandStringList.size
+ commandStringList.add(command)
+ }
+
+ /**
+ * 这个动态命令是否拥有指定的tag
+ *
+ * @param tag 目标tag
+ * @return 是否有这个tag
+ */
+ fun hasTag(tag: String): Boolean {
+ return tags.contains(tag)
+ }
+
+ /**
+ * 将这个动态命令解析为字符串
+ *
+ * @return
+ */
+ open fun analyze(): String {
+ val sb = StringBuilder()
+ for (c in commandStringList) {
+ sb.append(c)
+ }
+ commandStringList.clear()
+ commandStringList.add(sb.toString())
+ replacePoint.clear()
+ return sb.toString()
+ }
+
+ /**
+ * 转为宏命令。将会把所有可以替换的位点设置为宏参数。宏参数的名字和替换位点id相同
+ */
+ fun toMacro(): String {
+ val sb = StringBuilder()
+ for (c in commandStringList.indices) {
+ if (replacePoint.containsValue(c)) {
+ sb.append("{{${replacePoint.filter { it.value == c }.keys.first()}}}")
+ } else {
+ sb.append(commandStringList[c])
+ }
+ }
+ return sb.toString()
+ }
+
+ /**
+ * 替换目标位点中的字符串
+ *
+ * @param pointID 位点的ID
+ * @param target 目标字符串
+ *
+ * @return 如果没有可以替换的位点,则返回false
+ */
+ private fun replace(pointID: String, target: String): Boolean {
+ val point = replacePoint[pointID] ?: return false
+ commandStringList[point] = target
+ return true
+ }
+
+ fun replace(vararg pointIDtoTarget: Pair): Int {
+ var suc = 0
+ for (pt in pointIDtoTarget) {
+ if (replace(pt.first, pt.second)) suc++
+ }
+ return suc
+ }
+
+ fun get(pointID: String): String? {
+ val point = replacePoint[pointID] ?: return null
+ return commandStringList[point]
+ }
+
+ fun prepend(command: String) {
+ if (isCompleted) {
+ throw CommandException("Try to prepend argument to a completed command")
+ }
+ commandStringList.add(0, command)
+ }
+
+ fun prepend(command: Command) {
+ if (isCompleted) {
+ throw CommandException("Try to prepend argument to a completed command")
+ }
+ for (c in command.commandStringList) {
+ commandStringList.add(0, c)
+ }
+ replacePoint.putAll(command.replacePoint)
+ }
+
+ /**
+ * 在这条命令的末尾继续构建命令
+ *
+ * @param command 固定的命令字符串
+ * @param withBlank 是否会在此字符串和已有的字符串之间添加空格
+ * @return
+ */
+ fun build(command: String): Command {
+ commandStringList.add(command)
+ return this
+ }
+
+ fun build(command: Command): Command {
+ for (kv in command.replacePoint) {
+ replacePoint[kv.key] = kv.value + commandStringList.size
+ }
+ commandStringList.addAll(command.commandStringList)
+ return this
+ }
+
+ /**
+ * 在这条命令的末尾继续构建命令
+ *
+ * @param command 可被替换的命令字符串
+ * @param pointID 命令字符串的位点ID
+ * @return
+ */
+ fun build(command: String, pointID: String): Command {
+ replacePoint[pointID] = commandStringList.size
+ commandStringList.add(" ")
+ commandStringList.add(command)
+ return this
+ }
+
+ override fun toString(): String {
+ val sb = StringBuilder()
+ for (c in commandStringList) {
+ sb.append(c)
+ }
+ return sb.toString()
+ }
+
+ companion object {
+
+ /**
+ * 构建命令
+ *
+ * @param command 固定的命令字符串
+ * @return
+ */
+ fun build(command: String): Command {
+ return Command(command)
+ }
+
+ /**
+ * 构建命令
+ *
+ * @param command 可被替换的命令字符串
+ * @param pointID 命令字符串的位点ID
+ * @return
+ */
+ fun build(command: String, pointID: String): Command {
+ return Command(command, pointID)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/command/CommandList.kt b/src/main/kotlin/top/mcfpp/command/CommandList.kt
new file mode 100644
index 00000000..4868623e
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/command/CommandList.kt
@@ -0,0 +1,37 @@
+package top.mcfpp.command
+
+import top.mcfpp.Project
+
+class CommandList : ArrayList() {
+ fun analyzeAll(): ArrayList {
+ val re = ArrayList()
+ for (c in this) {
+ if (c is Comment && c.type < Project.config.commentLevel) continue
+ re.add(c.analyze())
+ }
+ return re
+ }
+
+ fun replaceAll(vararg pointIDtoTarget: Pair) {
+ for (c in this) {
+ c.replace(*pointIDtoTarget)
+ }
+ }
+
+ fun replaceThenAnalyze(vararg pointIDtoTarget: Pair) {
+ for (c in this) {
+ if (c.replace(*pointIDtoTarget) != 0) {
+ c.analyze()
+ }
+ }
+ }
+
+ fun add(element: String): Boolean {
+ return super.add(Command.build(element))
+ }
+
+ fun add(index: Int, element: String) {
+ return super.add(index, Command.build(element))
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/mcfpp/command/Commands.kt b/src/main/kotlin/top/mcfpp/command/Commands.kt
new file mode 100644
index 00000000..1fa2fd30
--- /dev/null
+++ b/src/main/kotlin/top/mcfpp/command/Commands.kt
@@ -0,0 +1,130 @@
+package top.mcfpp.command
+
+import top.mcfpp.Project
+import top.mcfpp.lang.CanSelectMember
+import top.mcfpp.lang.ClassPointer
+import top.mcfpp.lang.MCInt
+import top.mcfpp.lang.type.MCFPPClassType
+import top.mcfpp.model.function.Function
+
+/**
+ * 命令总类,提供了大量用于生成命令的方法。默认提供了一些可替换的位点
+ */
+object Commands {
+
+ /**
+ * function
+ *
+ * @param function
+ * @return
+ */
+ fun function(function: Function): Command {
+ return Command.build("function").build(function.namespaceID, function.namespaceID)
+ }
+
+
+ /**
+ * scoreboard players get
+ *
+ * @param target
+ * @return
+ */
+ fun sbPlayerGet(target: MCInt): Command {
+ return Command.build("scoreboard players get")
+ .build(target.name, target.name)
+ .build(target.`object`.toString(), target.`object`.toString())
+ }
+
+ /**
+ * scoreboard players add value
+ *
+ * @param target
+ * @param value
+ * @return
+ */
+ fun sbPlayerAdd(target: MCInt, value: Int): Command {
+ return Command.build("scoreboard players add")
+ .build(target.name, target.name)
+ .build(target.`object`.toString(), target.`object`.toString())
+ .build(" $value")
+ }
+
+ /**
+ * scoreboard players operation