Skip to content

Commit 37066a4

Browse files
committed
匿名联合数据模板以及数据模板的多继承
1 parent 0ee8043 commit 37066a4

File tree

12 files changed

+156
-50
lines changed

12 files changed

+156
-50
lines changed

src/main/antlr/mcfppLexer.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ SINGLE_QUOTE: '\'' ;
5050
//RIGHT_SHIFT_ARITHMETIC: '>>';
5151
//LEFT_SHIFT_ARITHMETIC: '<<';
5252
//RIGHT_SHIFT_LOGICAL: '>>>';
53-
//BIT_AND: '&';
53+
UNION: '&';
5454
//BIT_X_OR: '^';
5555
//BIT_OR: '|';
5656
//LEFT_SHIFT_ARITHMETIC_ASSIGN: '<<=';

src/main/antlr/mcfppParser.g4

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,12 @@ genericClassImplement
160160

161161
//数据模板
162162
templateDeclaration
163-
: FINAL? DATA classWithoutNamespace (COLON className)? templateBody
163+
: FINAL? DATA classWithoutNamespace (COLON className (',' className)*)? templateBody
164164
;
165165

166166
//数据模板
167167
objectTemplateDeclaration
168-
: FINAL? OBJECT DATA classWithoutNamespace (COLON className)? templateBody
168+
: FINAL? OBJECT DATA classWithoutNamespace (COLON className (',' className)*)? templateBody
169169
;
170170

171171
templateBody
@@ -563,6 +563,11 @@ type
563563
| LIST '<' type '>'
564564
| className readOnlyArgs?
565565
| Identifier
566+
| unionTemplateType
567+
;
568+
569+
unionTemplateType
570+
: '(' type (UNION type)* ')'
566571
;
567572

568573
normalType

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,25 @@ open class MCFPPFieldVisitor : mcfppParserBaseVisitor<Any?>() {
809809
DataTemplate.currTemplate = template
810810
currClassOrTemplate = template
811811
typeScope = template.field
812+
for (c in ctx.className()){
813+
//是否存在继承
814+
val (namespace, identifier) = StringHelper.splitNamespaceID(c.text)
815+
val s = GlobalField.getTemplate(namespace, identifier)
816+
if(s == null){
817+
val o = GlobalField.getObject(namespace, identifier)
818+
if(o is ObjectDataTemplate) {
819+
template.extends(o)
820+
}else{
821+
LogProcessor.error("Undefined template: " + c.text)
822+
}
823+
}else{
824+
if(s == template){
825+
LogProcessor.error("Infinitive reference: $id -> $identifier")
826+
}else{
827+
template.extends(s)
828+
}
829+
}
830+
}
812831
//解析成员
813832
//先解析函数和构造函数
814833
for (c in ctx.templateBody().templateMemberDeclaration()) {
@@ -844,6 +863,25 @@ open class MCFPPFieldVisitor : mcfppParserBaseVisitor<Any?>() {
844863
DataTemplate.currTemplate = objectTemplate
845864
currClassOrTemplate = objectTemplate
846865
typeScope = objectTemplate.field
866+
for (c in ctx.className()){
867+
//是否存在继承
868+
val (namespace, identifier) = StringHelper.splitNamespaceID(c.text)
869+
val s = GlobalField.getTemplate(namespace, identifier)
870+
if(s == null){
871+
val o = GlobalField.getObject(namespace, identifier)
872+
if(o is ObjectDataTemplate) {
873+
if(o == objectTemplate){
874+
LogProcessor.error("Infinitive reference: $id -> $identifier")
875+
}else{
876+
objectTemplate.extends(o)
877+
}
878+
}else{
879+
LogProcessor.error("Undefined template: " + c.text)
880+
}
881+
}else{
882+
objectTemplate.extends(s)
883+
}
884+
}
847885
//解析成员
848886
//先解析函数
849887
for (c in ctx.templateBody().templateMemberDeclaration()) {

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

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -312,27 +312,7 @@ class MCFPPTypeVisitor: mcfppParserBaseVisitor<Unit>() {
312312
DataTemplate.currTemplate = nsp.field.getTemplate(id)
313313
}
314314
val template = DataTemplate(id,Project.currNamespace)
315-
if (ctx.className() != null) {
316-
//存在继承
317-
val qwq = ctx.className().text.split(":")
318-
val identifier: String
319-
val namespace : String?
320-
if(qwq.size == 1){
321-
identifier = qwq[0]
322-
namespace = null
323-
}else{
324-
namespace = qwq[0]
325-
identifier = qwq[1]
326-
}
327-
val s = GlobalField.getTemplate(namespace, identifier)
328-
if(s == null){
329-
LogProcessor.error("Undefined template: " + ctx.className().text)
330-
}else{
331-
template.extends(s)
332-
}
333-
}else{
334-
template.extends(DataTemplate.baseDataTemplate)
335-
}
315+
template.extends(DataTemplate.baseDataTemplate)
336316
nsp.field.addTemplate(id, template)
337317
}
338318

@@ -350,23 +330,7 @@ class MCFPPTypeVisitor: mcfppParserBaseVisitor<Unit>() {
350330
return
351331
}
352332
val template = ObjectDataTemplate(id,Project.currNamespace)
353-
if (ctx.className() != null) {
354-
//是否存在继承
355-
val (namespace, identifier) = StringHelper.splitNamespaceID(ctx.className().text)
356-
val s = GlobalField.getTemplate(namespace, identifier)
357-
if(s == null){
358-
val o = GlobalField.getObject(namespace, identifier)
359-
if(o is ObjectDataTemplate) {
360-
template.extends(o)
361-
}else{
362-
LogProcessor.error("Undefined template: " + ctx.className().text)
363-
}
364-
}else{
365-
template.extends(s)
366-
}
367-
}else{
368-
template.extends(DataTemplate.baseDataTemplate)
369-
}
333+
template.extends(DataTemplate.baseDataTemplate)
370334
nsp.field.addObject(id, template)
371335
}
372336

src/main/kotlin/top/mcfpp/model/CompoundData.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import top.mcfpp.model.field.CompoundDataField
1111
import top.mcfpp.model.function.Function
1212
import top.mcfpp.model.function.NativeFunction
1313
import top.mcfpp.model.function.UnknownFunction
14+
import top.mcfpp.model.generic.GenericClass
1415
import top.mcfpp.type.MCFPPGenericParamType
1516
import top.mcfpp.util.LogProcessor
1617
import top.mcfpp.util.TextTranslator
@@ -300,6 +301,7 @@ open class CompoundData : FieldContainer, Serializable {
300301
fun forMember(operation: (Member) -> Any?){
301302
field.forEachFunction { operation(it) }
302303
field.forEachVar { operation(it) }
304+
field.forEachProperty { operation(it) }
303305
}
304306

305307
companion object {

src/main/kotlin/top/mcfpp/model/DataTemplate.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,26 @@ open class DataTemplate : FieldContainer, CompoundData {
120120
}
121121
}
122122

123+
override fun extends(compoundData: CompoundData): CompoundData {
124+
super.extends(compoundData)
125+
//把所有成员都塞进去
126+
compoundData.field.forEachVar {
127+
val b = field.getVar(it.identifier) != null
128+
if(b){
129+
LogProcessor.warn("Duplicate var ${it.identifier} in template ${compoundData.identifier}. Overriding it.")
130+
}
131+
field.putVar(it.identifier, it, true)
132+
}
133+
compoundData.field.forEachProperty {
134+
val b = field.getProperty(it.identifier) != null
135+
if(b){
136+
LogProcessor.warn("Duplicate property ${it.identifier} in template ${compoundData.identifier}. Overriding it.")
137+
}
138+
field.putProperty(it.identifier, it, true)
139+
}
140+
return this
141+
}
142+
123143
fun ifInfinitiveReference(template: DataTemplate): Boolean{
124144
return template == this && reference.any { it == template || it.ifInfinitiveReference(template) }
125145
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package top.mcfpp.model
2+
3+
class UnionDataTemplate(templates: List<DataTemplate>) :
4+
DataTemplate("union_${templates.joinToString("_") { it.identifier }}") {
5+
6+
init {
7+
templates.forEach { extends(it) }
8+
}
9+
10+
}

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ import top.mcfpp.antlr.MCFPPExprVisitor
88
import top.mcfpp.antlr.mcfppLexer
99
import top.mcfpp.antlr.mcfppParser
1010
import top.mcfpp.core.lang.Var
11-
import top.mcfpp.model.CanSelectMember
12-
import top.mcfpp.model.Class
13-
import top.mcfpp.model.CompoundData
14-
import top.mcfpp.model.FieldContainer
15-
import top.mcfpp.model.Member
1611
import top.mcfpp.model.field.GlobalField
1712
import top.mcfpp.model.field.IFieldWithType
1813
import top.mcfpp.model.function.ExtensionFunction
@@ -21,6 +16,7 @@ import top.mcfpp.model.function.UnknownFunction
2116
import top.mcfpp.model.generic.GenericClass
2217
import top.mcfpp.core.lang.UnknownVar
2318
import top.mcfpp.lib.TranslatableChatComponent
19+
import top.mcfpp.model.*
2420
import top.mcfpp.util.LogProcessor
2521
import top.mcfpp.util.StringHelper
2622
import top.mcfpp.util.TextTranslator
@@ -399,6 +395,22 @@ open class MCFPPType(
399395
val enum = GlobalField.getEnum(nspID.first, nspID.second)
400396
if(enum != null) return enum.getType()
401397
}
398+
//联合数据模板类型
399+
if(ctx.unionTemplateType() != null){
400+
val types = ArrayList<MCFPPDataTemplateType>()
401+
for (type in ctx.unionTemplateType().type()){
402+
val t = parseFromContext(type, typeScope)?: run {
403+
LogProcessor.error(TextTranslator.INVALID_TYPE_ERROR.translate(type.text))
404+
MCFPPBaseType.Any
405+
}
406+
if(t !is MCFPPDataTemplateType){
407+
LogProcessor.error("Union type can only be used with data template type")
408+
}else{
409+
types.add(t)
410+
}
411+
}
412+
return MCFPPDataTemplateType(UnionDataTemplate(types.map { it.template }), types)
413+
}
402414
//泛型类型
403415
if(typeScope.containType(ctx.text)){
404416
return typeScope.getType(ctx.text)!!

src/main/kotlin/top/mcfpp/util/NBTUtil.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ object NBTUtil {
3737
fun valueToNBT(any: Any?): Tag<*>{
3838
return when(any){
3939
null -> IntTag(0)
40-
is NBTBasedDataConcrete -> any.value
40+
is MCFPPValue<*> -> {
41+
varToNBT(any as Var<*>)?: StringTag(any.toString())
42+
}
4143
is Tag<*> -> any
4244
is Byte -> ByteTag(any)
4345
is Short -> ShortTag(any)

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,54 @@ class DataTemplateTest {
5151
MCFPPStringTest.readFromString(test, arrayOf("debug"))
5252
}
5353

54+
@Test
55+
fun extendTest(){
56+
val test =
57+
"""
58+
data Test{
59+
int qwq;
60+
}
61+
62+
data Test2: Test{
63+
string qwq2;
64+
}
65+
66+
func main(){
67+
Test2 t = {qwq:1,qwq2:"test"};
68+
print(t.qwq);
69+
print(t.qwq2);
70+
print(t);
71+
t.qwq = 6;
72+
print(t.qwq);
73+
print(t);
74+
t.qwq2 = "test2";
75+
print(t.qwq2);
76+
print(t);
77+
}
78+
""".trimIndent()
79+
MCFPPStringTest.readFromString(test)
80+
}
81+
82+
@Test
83+
fun unionTemplateTest(){
84+
val test =
85+
"""
86+
data Test1 {
87+
int qwq;
88+
}
89+
90+
data Test2 {
91+
string qwq2;
92+
}
93+
94+
func main(){
95+
(Test1&Test2) t = {qwq:1, qwq2: "qwq"};
96+
print(t);
97+
print(t.qwq);
98+
print(t.qwq2);
99+
}
100+
""".trimIndent()
101+
MCFPPStringTest.readFromString(test)
102+
}
103+
54104
}

0 commit comments

Comments
 (0)