Skip to content

Commit ca8464c

Browse files
committed
必定为可追踪的类型
1 parent ed13248 commit ca8464c

File tree

8 files changed

+76
-11
lines changed

8 files changed

+76
-11
lines changed

src/main/antlr/mcfppParser.g4

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ expressionList
573573
;
574574

575575
type
576+
: typeWithoutExcl EXCL?
577+
;
578+
579+
typeWithoutExcl
576580
: normalType
577581
| VecType
578582
| LIST '<' type '>'
@@ -602,7 +606,7 @@ normalType
602606
;
603607

604608
functionReturnType
605-
: type EXCL?
609+
: type
606610
| VOID
607611
;
608612

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ open class MCFPPFieldVisitor : mcfppParserBaseVisitor<Any?>() {
117117
null
118118
)
119119
f.returnType = ctx.functionReturnType()?.type()?.let {
120-
MCFPPType.parseFromContext(it.type(), typeScope)?: run {
120+
MCFPPType.parseFromContext(it.typeWithoutExcl().type(), typeScope)?: run {
121121
LogProcessor.error(TextTranslator.INVALID_TYPE_ERROR.translate(it.text))
122122
MCFPPBaseType.Any
123123
}
@@ -678,7 +678,7 @@ open class MCFPPFieldVisitor : mcfppParserBaseVisitor<Any?>() {
678678
Project.ctx = ctx!!
679679
val ownerType : Function.Companion.OwnerType
680680
//获取被拓展的类
681-
val data : CompoundData = if(ctx.type().className() == null){
681+
val data : CompoundData = if(ctx.type().typeWithoutExcl().className() == null){
682682
ownerType = Function.Companion.OwnerType.BASIC
683683
when(ctx.type().text){
684684
"int" -> MCInt.data
@@ -688,12 +688,12 @@ open class MCFPPFieldVisitor : mcfppParserBaseVisitor<Any?>() {
688688
}
689689
}
690690
}else{
691-
val (nsp, id) = StringHelper.splitNamespaceID(ctx.type().className().text)
691+
val (nsp, id) = StringHelper.splitNamespaceID(ctx.type().typeWithoutExcl().className().text)
692692
val qwq: Class? = GlobalField.getClass(nsp, id)
693693
if (qwq == null) {
694694
val pwp = GlobalField.getTemplate(nsp, id)
695695
if(pwp == null){
696-
LogProcessor.error("Undefined class or struct:" + ctx.type().className().text)
696+
LogProcessor.error("Undefined class or struct:" + ctx.type().typeWithoutExcl().className().text)
697697
return null
698698
}else{
699699
ownerType = Function.Companion.OwnerType.TEMPLATE

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,15 +249,15 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
249249

250250
fun enterExtensionFunctionDeclaration(ctx: mcfppParser.ExtensionFunctionDeclarationContext) {
251251
val f: Function
252-
val data: CompoundData = if (ctx.type().className() == null) {
252+
val data: CompoundData = if (ctx.type().typeWithoutExcl().className() == null) {
253253
when (ctx.type().text) {
254254
"int" -> MCInt.data
255255
else -> {
256256
throw Exception("Cannot add extension function to ${ctx.type().text}")
257257
}
258258
}
259259
} else {
260-
val clsStr = ctx.type().className().text.split(":")
260+
val clsStr = ctx.type().typeWithoutExcl().className().text.split(":")
261261
val id: String
262262
val nsp: String?
263263
if (clsStr.size == 1) {
@@ -271,7 +271,7 @@ open class MCFPPImVisitor: mcfppParserBaseVisitor<Any?>() {
271271
if (owo == null) {
272272
val pwp = GlobalField.getTemplate(nsp, id)
273273
if (pwp == null) {
274-
LogProcessor.error("Undefined class or struct:" + ctx.type().className().text)
274+
LogProcessor.error("Undefined class or struct:" + ctx.type().typeWithoutExcl().className().text)
275275
f = UnknownFunction(ctx.Identifier().text)
276276
Function.currFunction = f
277277
return

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ abstract class Var<Self: Var<Self>> : Member, Cloneable, CanSelectMember, Serial
175175
if(v.isError){
176176
v = b
177177
}
178+
if(type is MCFPPDeclaredConcreteType && v !is MCFPPValue<*>){
179+
LogProcessor.error("Cannot assign a non-value variable to a declared-concrete variable.")
180+
return this as Self
181+
}
178182
val re = doAssignedBy(v)
179183
re.isDynamic = isDynamic
180184
re.hasAssigned = true
@@ -499,6 +503,10 @@ abstract class Var<Self: Var<Self>> : Member, Cloneable, CanSelectMember, Serial
499503
override fun replaceMemberVar(v: Var<*>){}
500504

501505
open fun replacedBy(v : Var<*>){
506+
if(this.type is MCFPPDeclaredConcreteType && v !is MCFPPValue<*>){
507+
LogProcessor.error("Cannot assign a non-value variable to a declared-concrete variable.")
508+
return
509+
}
502510
if(v == this) return
503511
if(v is MCInt && this is MCInt && holder != null){
504512
holder!!.replaceScore(v)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import top.mcfpp.core.lang.MCFPPValue
1616
import top.mcfpp.model.*
1717
import top.mcfpp.model.field.FunctionField
1818
import top.mcfpp.model.generic.Generic
19+
import top.mcfpp.type.MCFPPDeclaredConcreteType
1920
import top.mcfpp.util.LogProcessor
2021
import top.mcfpp.util.StringHelper
2122
import top.mcfpp.util.TextTranslator
@@ -719,6 +720,10 @@ open class Function : Member, FieldContainer, Serializable {
719720
LogProcessor.error("Function $identifier has no return value but tried to return a ${v.type}")
720721
return
721722
}
723+
if((returnVar.hasAssigned || v !is MCFPPValue<*>) && returnVar.type is MCFPPDeclaredConcreteType){
724+
LogProcessor.error("Function $namespaceID must return a concrete value")
725+
return
726+
}
722727
returnVar = returnVar.assignedBy(v)
723728
}
724729

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package top.mcfpp.type
2+
3+
import net.querz.nbt.tag.Tag
4+
import top.mcfpp.core.lang.Var
5+
import top.mcfpp.model.FieldContainer
6+
7+
class MCFPPDeclaredConcreteType(val type: MCFPPType): MCFPPConcreteType(type.objectData, arrayListOf(type)) {
8+
9+
override val typeName: String
10+
get() = type.typeName
11+
12+
override val nbtType: Class<out Tag<*>>
13+
get() = type.nbtType
14+
15+
override fun build(identifier: String): Var<*> = type.build(identifier).apply { type = this@MCFPPDeclaredConcreteType }
16+
17+
override fun build(identifier: String, container: FieldContainer): Var<*> = type.build(identifier, container).apply { type = this@MCFPPDeclaredConcreteType }
18+
19+
override fun build(identifier: String, clazz: top.mcfpp.model.Class): Var<*> = type.build(identifier, clazz).apply { type = this@MCFPPDeclaredConcreteType }
20+
21+
}

src/main/kotlin/top/mcfpp/type/MCFPPType.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import org.antlr.v4.runtime.CommonTokenStream
77
import top.mcfpp.antlr.MCFPPExprVisitor
88
import top.mcfpp.antlr.mcfppLexer
99
import top.mcfpp.antlr.mcfppParser
10+
import top.mcfpp.antlr.mcfppParser.TypeContext
11+
import top.mcfpp.antlr.mcfppParser.TypeWithoutExclContext
1012
import top.mcfpp.core.lang.Var
1113
import top.mcfpp.model.field.GlobalField
1214
import top.mcfpp.model.field.IFieldWithType
@@ -298,6 +300,10 @@ open class MCFPPType(
298300
* 根据类型标识符中获取一个类型
299301
*/
300302
fun parseFromIdentifier(identifier: String, typeScope: IFieldWithType): MCFPPType? {
303+
if(identifier.last() == '!'){
304+
val qwq = parseFromIdentifier(identifier.substring(0, identifier.length - 1), typeScope)
305+
return qwq?.let { MCFPPDeclaredConcreteType(qwq) }
306+
}
301307
if(identifier.contains("<")){
302308
val charStream: CharStream = CharStreams.fromString(identifier)
303309
val tokens = CommonTokenStream(mcfppLexer(charStream))
@@ -355,7 +361,16 @@ open class MCFPPType(
355361
return null
356362
}
357363

358-
fun parseFromContext(ctx: mcfppParser.TypeContext, typeScope: IFieldWithType): MCFPPType? {
364+
fun parseFromContext(ctx: TypeContext, typeScope: IFieldWithType): MCFPPType?{
365+
val qwq = parseFromContext(ctx.typeWithoutExcl(), typeScope)
366+
return if(ctx.EXCL() != null){
367+
qwq?.let { MCFPPDeclaredConcreteType(it) }
368+
}else{
369+
qwq
370+
}
371+
}
372+
373+
private fun parseFromContext(ctx: TypeWithoutExclContext, typeScope: IFieldWithType): MCFPPType? {
359374
if(ctx.normalType() != null){
360375
return typeCache[ctx.text]!!
361376
}
@@ -377,12 +392,12 @@ open class MCFPPType(
377392
val clazz = GlobalField.getClass(nspID.first, nspID.second)
378393
if(clazz != null) {
379394
if(clazz is GenericClass){
380-
if(clazz.readOnlyParams.size != ctx.type().readOnlyArgs()?.expressionList()?.expression()?.size){
395+
if(clazz.readOnlyParams.size != ctx.readOnlyArgs()?.expressionList()?.expression()?.size){
381396
LogProcessor.error("Generic class ${clazz.identifier} requires ${clazz.readOnlyParams.size} type arguments, but ${ctx.readOnlyArgs().expressionList().expression().size} were provided")
382397
return MCFPPBaseType.Any
383398
}
384399
val expr = MCFPPExprVisitor()
385-
val readOnlyArgs = ctx.type().readOnlyArgs()?.expressionList()?.expression()?.map { expr.visit(it)!! } ?: listOf()
400+
val readOnlyArgs = ctx.readOnlyArgs()?.expressionList()?.expression()?.map { expr.visit(it)!! } ?: listOf()
386401
return clazz.compile(readOnlyArgs).getType()
387402
}else{
388403
return clazz.getType()

src/test/kotlin/top/mcfpp/test/BaseTest.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,16 @@ class BaseTest {
9696
MCFPPStringTest.readFromString(test)
9797
}
9898

99+
@Test
100+
fun concreteTest(){
101+
val test =
102+
"""
103+
func test() -> int!{
104+
dynamic int a = 1;
105+
return a;
106+
}
107+
""".trimIndent()
108+
MCFPPStringTest.readFromString(test)
109+
}
110+
99111
}

0 commit comments

Comments
 (0)