Skip to content

Commit e1eee11

Browse files
authored
[WIP] First step towards new generics (#796)
This is the first step towards the new Generics design (see #679). This pull requests adds support for template generics. The behavior of existing code should not change. To use template generics, add a colon (`:`) after the type parameter name.
1 parent 1cc9c7d commit e1eee11

File tree

93 files changed

+4054
-580
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+4054
-580
lines changed

de.peeeq.wurstscript/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ dependencies {
7070
antlr "org.antlr:antlr4:4.7"
7171

7272
// tool for generating AST-classes
73-
compileOnly 'com.github.peterzeller:abstractsyntaxgen:0.3.1'
73+
compileOnly 'com.github.peterzeller:abstractsyntaxgen:59168ba9d61d89c775a53d54b3b83a99f48a585b'
7474

7575
// JUnit for testing
7676
testCompile group: 'org.testng', name: 'testng', version: '6.14.3'

de.peeeq.wurstscript/deploy.gradle

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -41,51 +41,50 @@ create_zip_wurstpack_compiler.dependsOn(make_for_wurstpack)
4141

4242
task create_zips {
4343
doLast {
44-
mkdir("../downloads/")
45-
copy {
46-
from 'build/distributions/'
47-
into '../downloads/'
48-
}
49-
copy {
50-
from 'build/install/wurstscript/lib/wurstscript.jar'
51-
into '../downloads/'
52-
}
53-
copy {
54-
from '../Wurstpack'
55-
into '../downloads/Wurstpack/'
56-
}
57-
copy {
58-
from '../WurstSetup/build/libs/WurstSetup.jar'
59-
into '../downloads/'
60-
}
61-
// create checksums
62-
mkdir("../Checksums/bin")
44+
mkdir("../downloads/")
45+
copy {
46+
from 'build/distributions/'
47+
into '../downloads/'
48+
}
49+
copy {
50+
from 'build/install/wurstscript/lib/wurstscript.jar'
51+
into '../downloads/'
52+
}
53+
copy {
54+
from '../Wurstpack'
55+
into '../downloads/Wurstpack/'
56+
}
57+
copy {
58+
from '../WurstSetup/build/libs/WurstSetup.jar'
59+
into '../downloads/'
60+
}
61+
// create checksums
62+
mkdir("../Checksums/bin")
6363

64-
javaexec {
65-
classpath = sourceSets.main.runtimeClasspath
66-
main = "de.peeeq.wurstio.Checksums"
67-
args = ["../downloads/Wurstpack/",
68-
"../downloads/wurstpack.md5"]
69-
}
64+
javaexec {
65+
classpath = sourceSets.main.runtimeClasspath
66+
main = "de.peeeq.wurstio.Checksums"
67+
args = ["../downloads/Wurstpack/",
68+
"../downloads/wurstpack.md5"]
69+
}
7070
}
71-
7271
}
7372
create_zips.dependsOn(installDist)
7473
create_zips.dependsOn(create_zip_wurstpack_complete)
7574
create_zips.dependsOn(create_zip_wurstpack_compiler)
7675

7776
task generate_hotdoc {
7877
doLast {
79-
copy {
80-
from("/src/main/resources/")
81-
into("/build/classes/main/")
82-
}
83-
javaexec {
84-
classpath = sourceSets.main.runtimeClasspath
85-
main = "de.peeeq.wurstio.Main"
86-
args = ["--hotdoc",
87-
"./build/deps/",
88-
"../downloads/hotdoc"]
78+
copy {
79+
from("/src/main/resources/")
80+
into("/build/classes/main/")
81+
}
82+
javaexec {
83+
classpath = sourceSets.main.runtimeClasspath
84+
main = "de.peeeq.wurstio.Main"
85+
args = ["--hotdoc",
86+
"./build/deps/",
87+
"../downloads/hotdoc"]
8988
}
9089
}
9190
}

de.peeeq.wurstscript/parserspec/jass_im.parseq

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ abstract syntax:
66
ImProg(
77
@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
88
ImVars globals,
9-
ImFunctions functions,
10-
ImClasses classes,
9+
ImFunctions functions,
10+
ImMethods methods,
11+
ImClasses classes,
12+
ImTypeClassFuncs typeClassFunctions,
1113
java.util.Map<ImVar, java.util.List<ImExpr>> globalInits)
1214

1315
ImVars * ImVar
1416
ImFunctions * ImFunction
1517
ImClasses * ImClass
18+
ImTypeClassFuncs * ImTypeClassFunc
1619

1720
ImVar(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImType type, String name, boolean isBJ)
1821

@@ -22,25 +25,42 @@ ImType =
2225
| ImArrayTypeMulti(ref ImType entryType, java.util.List<Integer> arraySize)
2326
| ImTupleType(java.util.List<ImType> types, java.util.List<String> names)
2427
| ImVoid()
25-
28+
| ImClassType(ref ImClass classDef, ImTypeArguments typeArguments)
29+
| ImTypeVarRef(ref ImTypeVar typeVariable)
30+
31+
ImTypeVars * ImTypeVar
32+
33+
ImTypeVar(String name)
34+
2635
ImFunction(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
27-
String name,
36+
String name,
37+
ImTypeVars typeVariables,
2838
ImVars parameters,
2939
ref ImType returnType,
3040
ImVars locals,
3141
ImStmts body,
3242
java.util.List<de.peeeq.wurstscript.translation.imtranslation.FunctionFlag> flags)
3343

44+
ImTypeClassFunc(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
45+
String name,
46+
ImTypeVars typeVariables,
47+
ImVars parameters,
48+
ref ImType returnType)
49+
50+
3451
ImClass(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
35-
String name,
52+
String name,
53+
ImTypeVars typeVariables,
3654
ImVars fields,
37-
ImMethods methods,
38-
java.util.List<ImClass> superClasses)
55+
ImMethods methods,
56+
ImFunctions functions,
57+
java.util.List<ImClassType> superClasses)
3958

4059
ImMethods * ImMethod
4160

42-
ImMethod(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
43-
String name,
61+
ImMethod(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace,
62+
ref ImClassType methodClass,
63+
String name,
4464
ref ImFunction implementation,
4565
java.util.List<ImMethod> subMethods,
4666
boolean isAbstract)
@@ -75,6 +95,9 @@ ImExpr =
7595
| ImGetStackTrace()
7696
| ImCompiletimeExpr(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ImExpr expr, int executionOrderIndex)
7797
| ImLExpr
98+
| ImTypeVarDispatch(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImTypeClassFunc typeClassFunc, ImExprs arguments
99+
, ref ImTypeVar typeVariable)
100+
| ImCast(ImExpr expr, ref ImType toType)
78101

79102
// an expression which can be used on the left hand side of an assignment
80103
ImLExpr =
@@ -87,18 +110,26 @@ ImLExpr =
87110

88111

89112

90-
ImClassRelatedExpr =
91-
ImMethodCall(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImMethod method, ImExpr receiver, ImExprs arguments, boolean tuplesEliminated)
92-
| ImAlloc(ref ImClass clazz)
93-
| ImDealloc(ref ImClass clazz, ImExpr obj)
94-
| ImMemberAccess(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ImExpr receiver, ref ImVar var)
95-
| ImInstanceof(ImExpr obj, ref ImClass clazz)
96-
| ImTypeIdOfObj(ImExpr obj, ref ImClass clazz)
97-
| ImTypeIdOfClass(ref ImClass clazz)
113+
ImClassRelatedExpr =
114+
ImMemberOrMethodAccess
115+
| ImClassRelatedExprWithClass
116+
117+
ImMemberOrMethodAccess =
118+
ImMethodCall(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImMethod method, ImTypeArguments typeArguments, ImExpr receiver, ImExprs arguments, boolean tuplesEliminated)
119+
| ImMemberAccess(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ImExpr receiver, ImTypeArguments typeArguments, ref ImVar var, ImExprs indexes)
120+
121+
ImClassRelatedExprWithClass =
122+
ImAlloc(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImClassType clazz)
123+
| ImDealloc(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImClassType clazz, ImExpr obj)
124+
| ImInstanceof(ImExpr obj, ref ImClassType clazz)
125+
| ImTypeIdOfObj(ImExpr obj, ref ImClassType clazz)
126+
| ImTypeIdOfClass(ref ImClassType clazz)
98127

99128

129+
130+
100131
ImCall =
101-
ImFunctionCall(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImFunction func, ImExprs arguments
132+
ImFunctionCall(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImFunction func, ImTypeArguments typeArguments, ImExprs arguments
102133
, boolean tuplesEliminated, de.peeeq.wurstscript.translation.imtranslation.CallType callType)
103134
| ImOperatorCall(de.peeeq.wurstscript.WurstOperator op, ImExprs arguments)
104135

@@ -107,9 +138,13 @@ ImConst =
107138
| ImRealVal(String valR)
108139
| ImStringVal(String valS)
109140
| ImBoolVal(boolean valB)
110-
| ImFuncRef(ref ImFunction func)
141+
| ImFuncRef(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImFunction func)
111142
| ImNull(ref ImType type)
112143

144+
ImTypeArguments * ImTypeArgument
145+
146+
ImTypeArgument(ref ImType type, java.util.Map<ImTypeClassFunc, fj.data.Either<ImMethod, ImFunction>> typeClassBinding)
147+
113148
// helper types:
114149

115150

@@ -118,14 +153,15 @@ JassImElementWithName = ImVar | ImFunction | ImClass | ImMethod
118153
ElementWithTrace = ImVar | ImFunction | ImClass | ImMethod | ImIf | ImLoop | ImExitwhen | ImReturn
119154
| ImSet | ImSetTuple | ImSetArray | ImSetArrayMulti | ImSetArrayTuple
120155
| ImMethodCall | ImFunctionCall | ImCompiletimeExpr | ImVarArrayAccess | ImMemberAccess
121-
| ImProg
156+
| ImProg | ImFuncRef
157+
| ImAlloc | ImDealloc
122158

123159
ElementWithTypes = ImTupleType | ImTupleArrayType
124160

125161
ElementWithVar = ImVarAccess | ImVarArrayAccess | ImVarArrayMultiAccess | ImMemberAccess
126162

127163

128-
ImPrintable = ImStmt | ImFunction | ImProg | ImVar | ImType | ImStmts | ImExprOpt
164+
ImPrintable = ImStmt | ImFunction | ImProg | ImVar | ImType | ImStmts | ImExprOpt | ImType | ImTypeVar | ImClass
129165

130166
ImVarWrite = ImSet | ImSetArray | ImSetArrayMulti | ImSetArrayTuple | ImSetTuple
131167
ImVarRead = ImVarAccess | ImVarArrayAccess | ImVarArrayMultiAccess
@@ -140,7 +176,7 @@ ImPrintable.print(java.lang.Appendable sb, int indent)
140176
returns void
141177
implemented by de.peeeq.wurstscript.translation.imtranslation.ImPrinter.print
142178

143-
ImPrintable.toString()
179+
Element.toString()
144180
returns String
145181
implemented by de.peeeq.wurstscript.translation.imtranslation.ImPrinter.asString
146182

@@ -315,7 +351,7 @@ ImMethod.attrClass()
315351
returns ImClass
316352
implemented by de.peeeq.wurstscript.translation.imtojass.ImAttributes.attrClass
317353

318-
ImClass.attrTypeId
354+
ImClass.attrTypeId()
319355
returns int
320356
implemented by de.peeeq.wurstscript.translation.imtranslation.TypeId.get
321357

@@ -338,4 +374,4 @@ ImProg.attrSubclasses
338374
ImLExpr.isUsedAsLValue()
339375
returns boolean
340376
implemented by de.peeeq.wurstscript.translation.imtranslation.LValues.isUsedAsLValue
341-
377+

de.peeeq.wurstscript/parserspec/wurstscript.parseq

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ ArraySizes * Expr
115115

116116
TypeParamDefs * TypeParamDef
117117

118-
TypeParamDef(de.peeeq.wurstscript.parser.WPos source, Modifiers modifiers, Identifier nameId)
118+
TypeParamDef(de.peeeq.wurstscript.parser.WPos source, Modifiers modifiers, Identifier nameId, TypeParamConstraints typeParamConstraints)
119+
120+
TypeParamConstraints = NoTypeParamConstraints() | TypeExprList
119121

120122

121123
WParameters * WParameter
@@ -343,7 +345,9 @@ AstElementWithIndexes = ExprMemberArrayVar | ExprVarArrayAccess
343345

344346
ClassOrModule = ClassDef | ModuleDef
345347

346-
StructureDef = ClassOrModuleOrModuleInstanciation | InterfaceDef
348+
StructureDef = ClassOrModuleOrModuleInstanciation | ClassOrInterface
349+
350+
ClassOrInterface = ClassDef | InterfaceDef
347351

348352
ClassOrModuleInstanciation = ClassDef | ModuleInstanciation
349353
ClassOrModuleOrModuleInstanciation = ClassOrModule | ClassOrModuleInstanciation
@@ -518,6 +522,10 @@ Element.attrNearestClassDef()
518522
returns @Nullable ClassDef
519523
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestClassDef
520524

525+
Element.attrNearestClassOrInterface()
526+
returns @Nullable ClassOrInterface
527+
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestClassOrInterface
528+
521529
Element.attrNearestClassOrModule()
522530
returns @Nullable ClassOrModule
523531
implemented by de.peeeq.wurstscript.attributes.AttrNearest.nearestClassOrModule

de.peeeq.wurstscript/src/main/antlr/de/peeeq/wurstscript/antlr/Wurst.g4

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ classDef:
132132
ENDBLOCK)?
133133
;
134134

135+
typeclassDef:
136+
modifiersWithDoc 'typeclass' name=ID typeParams
137+
('extends' implemented+=typeExpr (',' implemented+=typeExpr)*)?
138+
NL (STARTBLOCK
139+
classSlots
140+
ENDBLOCK)?
141+
;
142+
143+
135144
enumDef: modifiersWithDoc 'enum' name=ID NL (STARTBLOCK
136145
(enumMembers+=ID NL)*
137146
ENDBLOCK)?;
@@ -406,7 +415,10 @@ shortFormalParameter: typeExpr? name=ID;
406415

407416
typeParams: ('<' (params+=typeParam (',' params+=typeParam)*)? '>')?;
408417

409-
typeParam: name=ID;
418+
typeParam: name=ID typeParamConstraints?;
419+
420+
typeParamConstraints: ':' (constraints+=typeExpr ('and' constraints+=typeExpr)*)?;
421+
410422

411423
stmtForLoop:
412424
forRangeLoop

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompilationProcess.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ protected void print(String message) {
156156
runTests.runTests(compiler.getImProg(), null, null);
157157

158158
for (RunTests.TestFailure e : runTests.getFailTests()) {
159-
gui.sendError(new CompileError(e.getFunction().attrTrace().attrErrorPos(), e.getMessage()));
159+
gui.sendError(new CompileError(e.getFunction(), e.getMessage()));
160160
if (runArgs.isGui()) {
161161
// when using graphical user interface, send stack trace to GUI
162162
for (ILStackFrame sf : Utils.iterateReverse(e.getStackTrace().getStackFrames())) {

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompiletimeFunctionRunner.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private ImExpr constantToExprHashtable(ImCompiletimeExpr cte, Element trace, Arr
267267
WPos errorPos = trace.attrErrorPos();
268268
ImFunction initHashtable = findNative("InitHashtable", errorPos);
269269
ImStmts stmts = JassIm.ImStmts(
270-
JassIm.ImSet(trace, JassIm.ImVarAccess(htVar), JassIm.ImFunctionCall(trace, initHashtable, JassIm.ImExprs(), false, CallType.NORMAL))
270+
JassIm.ImSet(trace, JassIm.ImVarAccess(htVar), JassIm.ImFunctionCall(trace, initHashtable, JassIm.ImTypeArguments(), JassIm.ImExprs(), false, CallType.NORMAL))
271271
);
272272

273273
// we have to collect all values after all compiletime functions have run, so use delayedActions
@@ -278,7 +278,7 @@ private ImExpr constantToExprHashtable(ImCompiletimeExpr cte, Element trace, Arr
278278
if (v instanceof ILconstInt) {
279279
ILconstInt iv = (ILconstInt) v;
280280
ImFunction SaveInteger = findNative("SaveInteger", errorPos);
281-
stmts.add(JassIm.ImFunctionCall(trace, SaveInteger, JassIm.ImExprs(
281+
stmts.add(JassIm.ImFunctionCall(trace, SaveInteger, JassIm.ImTypeArguments(), JassIm.ImExprs(
282282
JassIm.ImVarAccess(htVar),
283283
JassIm.ImIntVal(key.getParentkey()),
284284
JassIm.ImIntVal(key.getChildkey()),

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ public JassProg transformProgToJass() {
394394
imTranslator2.assertProperties();
395395
checkNoCompiletimeExpr(imProg2);
396396
int stage = 2;
397+
// eliminate
398+
beginPhase(2, "Eliminate generics");
399+
new EliminateGenerics(imTranslator2, imProg2).transform();
400+
printDebugImProg("./test-output/im " + stage++ + "_genericsEliminated.im");
401+
397402
// eliminate classes
398403
beginPhase(2, "translate classes");
399404

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/HoverInfo.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,11 @@ public List<Either<String, MarkedString>> case_NativeType(NativeType nativeType)
571571
return description(nativeType);
572572
}
573573

574+
@Override
575+
public List<Either<String, MarkedString>> case_NoTypeParamConstraints(NoTypeParamConstraints noTypeParamConstraints) {
576+
return string("No type parameter constraints given.");
577+
}
578+
574579
@Override
575580
public List<Either<String, MarkedString>> case_StmtForRangeUp(StmtForRangeUp stmtForRangeUp) {
576581
return string("Execute the body several times, counting up");

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/ModuleExpander.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public static ModuleInstanciations expandModules(ModuleInstanciation mi) {
109109
return mi.getP_moduleInstanciations();
110110
}
111111

112-
private static <T extends Element> T smartCopy(T e, List<Pair<WurstType, WurstType>> typeReplacements) {
112+
public static <T extends Element> T smartCopy(T e, List<Pair<WurstType, WurstType>> typeReplacements) {
113113
List<Pair<ImmutableList<Integer>, TypeExpr>> replacementsByPath = Lists.newArrayList();
114114
calcReplacementsByPath(typeReplacements, replacementsByPath, e, ImmutableList.<Integer>emptyList());
115115

@@ -118,7 +118,7 @@ private static <T extends Element> T smartCopy(T e, List<Pair<WurstType, WurstTy
118118

119119
// Do the type replacements
120120
for (Pair<ImmutableList<Integer>, TypeExpr> rep : replacementsByPath) {
121-
doReplacement(copy, rep.getA(), (TypeExpr) rep.getB().copy());
121+
doReplacement(copy, rep.getA(), rep.getB().copy());
122122
}
123123

124124
@SuppressWarnings("unchecked")

0 commit comments

Comments
 (0)