Skip to content

Commit 0dc510f

Browse files
authored
fix new generic static functions (#1195)
1 parent 6d01dbb commit 0dc510f

13 files changed

Lines changed: 275 additions & 11 deletions

File tree

de.peeeq.wurstscript/parserspec/wurstscript.parseq

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ Expr =
180180
| ExprMember
181181
| ExprFunctionCall(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Identifier funcNameId, TypeExprList typeArgs, Arguments args)
182182
| ExprNewObject(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Identifier typeNameId, TypeExprList typeArgs, Arguments args)
183+
| ExprTypeRef(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ)
183184
| ExprCast(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ, Expr expr)
184185
| ExprInstanceOf(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ, Expr expr)
185186
| ExprClosure(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, @ignoreForEquality de.peeeq.wurstscript.parser.WPos arrowSource, WShortParameters shortParameters, Expr implementation)

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ indexes:
350350

351351

352352
expr:
353-
exprPrimary
353+
receiverType=genericTypeReceiver dotsTypeCall=('.'|'..') typeFuncName=ID? typeCallTypeArgs=typeArgs typeCallArgs=argumentList
354+
| exprPrimary
354355
| left=expr 'castTo' castToType=typeExpr
355356
| left=expr 'instanceof' instaneofType=typeExpr
356357
| receiver=expr dotsCall=('.'|'..') funcName=ID? typeArgs argumentList
@@ -443,6 +444,20 @@ stmtSkip:'skip';
443444

444445
typeArgs: ('<' (args+=typeExpr (',' args+=typeExpr)*)? '>')?;
445446

447+
typeArgsNonEmpty: '<' args+=typeExpr (',' args+=typeExpr)* '>';
448+
449+
genericTypeReceiver:
450+
receiverTypePrefixes+=genericTypeReceiverPrefixPart* receiverTypeGenericPart=genericTypeReceiverGenericPart
451+
;
452+
453+
genericTypeReceiverPrefixPart:
454+
typeName=ID '.'
455+
;
456+
457+
genericTypeReceiverGenericPart:
458+
typeName=ID typeArgsNonEmpty
459+
;
460+
446461
exprList : exprs+=expr (',' exprs+=expr)*;
447462

448463

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
@@ -688,6 +688,11 @@ public List<Either<String, MarkedString>> case_TypeExprSimple(TypeExprSimple t)
688688
return typeExpr(t);
689689
}
690690

691+
@Override
692+
public List<Either<String, MarkedString>> case_ExprTypeRef(ExprTypeRef e) {
693+
return typeExpr(e.getTyp());
694+
}
695+
691696
@Override
692697
public List<Either<String, MarkedString>> case_Modifiers(Modifiers modifiers) {
693698
return string("Modifiers for this declaration.");

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public static WurstType calculate(ExprFuncRef term) {
4545
return WurstTypeCode.instance();
4646
}
4747

48+
public static WurstType calculate(ExprTypeRef term) {
49+
return term.getTyp().attrTyp();
50+
}
51+
4852

4953
public static WurstType calculate(ExprVarAccess term) {
5054
NameLink varDef = term.attrNameLink();

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrPossibleFunctionSignatures.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static ImmutableCollection<FunctionSignature> calculate(FunctionCall fc)
3737
}
3838
} // TODO else check?
3939

40-
VariableBinding mapping = givenBinding(fc, sig.getDefinitionTypeVariables());
40+
VariableBinding mapping = sig.getMapping().union(givenBinding(fc, sig.getDefinitionTypeVariables()));
4141
sig = sig.setTypeArgs(fc, mapping);
4242

4343
resultBuilder.add(sig);
@@ -229,7 +229,7 @@ public static ImmutableCollection<FunctionSignature> calculate(ExprMemberMethod
229229
}
230230

231231
// Apply explicit type args from the call-site (e.g., c.foo<T,...>(...))
232-
VariableBinding explicit = GenericsHelper.givenBinding(mm, sig.getDefinitionTypeVariables());
232+
VariableBinding explicit = sig.getMapping().union(GenericsHelper.givenBinding(mm, sig.getDefinitionTypeVariables()));
233233
sig = sig.setTypeArgs(mm, explicit);
234234

235235
prepared.add(sig);

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/DescriptionHtml.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ public static String description(ExprThis e) {
207207
return "this has type " + htmlType(e.attrTyp());
208208
}
209209

210+
public static String description(ExprTypeRef e) {
211+
return "Type reference " + htmlType(e.attrTyp());
212+
}
213+
210214
public static String description(ExprTypeId exprTypeId) {
211215
return "typeId: returns the typeId of an object or class. The typeId is "
212216
+ "a unique number for each class in the same type hierarchy.";

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/ReadVariables.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ public static ImmutableList<NameDef> calculate(ExprFuncRef exprFuncRef) {
112112
return ImmutableList.emptyList();
113113
}
114114

115+
public static ImmutableList<NameDef> calculate(ExprTypeRef exprTypeRef) {
116+
return ImmutableList.emptyList();
117+
}
118+
115119
public static ImmutableList<NameDef> calculate(ExprTypeId e) {
116120
return e.getLeft().attrReadVariables();
117121
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/prettyPrint/PrettyPrinter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ public static void prettyPrint(ExprThis e, Spacer spacer, StringBuilder sb, int
487487
sb.append("this");
488488
}
489489

490+
public static void prettyPrint(ExprTypeRef e, Spacer spacer, StringBuilder sb, int indent) {
491+
e.getTyp().prettyPrint(spacer, sb, indent);
492+
}
493+
490494
public static void prettyPrint(ExprTypeId e, Spacer spacer, StringBuilder sb, int indent) {
491495
e.getLeft().prettyPrint(spacer, sb, indent);
492496
sb.append(".typeId");

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import de.peeeq.wurstio.jassinterpreter.VarargArray;
66
import de.peeeq.wurstscript.WLogger;
77
import de.peeeq.wurstscript.ast.Annotation;
8+
import de.peeeq.wurstscript.ast.ClassOrInterface;
9+
import de.peeeq.wurstscript.ast.FuncDef;
810
import de.peeeq.wurstscript.ast.HasModifier;
911
import de.peeeq.wurstscript.ast.Modifier;
1012
import de.peeeq.wurstscript.gui.WurstGui;
@@ -172,6 +174,15 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
172174
subst.put(fvars.get(i2), targs.get(i2).getType());
173175
}
174176

177+
ImClass sourceOwner = findSourceOwnerClass(f, globalState.getProg());
178+
if (sourceOwner != null) {
179+
ImTypeVars cvars = sourceOwner.getTypeVariables();
180+
int n2 = Math.min(cvars.size(), targs.size());
181+
for (int i2 = 0; i2 < n2; i2++) {
182+
subst.put(cvars.get(i2), targs.get(i2).getType());
183+
}
184+
}
185+
175186
// 2) If the function is inside a class, also bind class type vars with the same call type args
176187
Element owner = f.getParent();
177188
while (owner != null && !(owner instanceof ImClass)) {
@@ -249,6 +260,26 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
249260
}
250261
}
251262

263+
private static @Nullable ImClass findSourceOwnerClass(ImFunction f, ImProg prog) {
264+
if (!(f.getTrace() instanceof FuncDef)) {
265+
return null;
266+
}
267+
FuncDef fd = (FuncDef) f.getTrace();
268+
if (!fd.attrIsStatic()) {
269+
return null;
270+
}
271+
ClassOrInterface owner = fd.attrNearestClassOrInterface();
272+
if (owner == null) {
273+
return null;
274+
}
275+
for (ImClass c : prog.getClasses()) {
276+
if (c.getTrace() == owner) {
277+
return c;
278+
}
279+
}
280+
return null;
281+
}
282+
252283

253284
public static de.peeeq.wurstscript.ast.Element getTrace(ProgramState globalState, ImFunction f) {
254285
Element lastStatement = globalState.getLastStatement();

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/parser/antlr/AntlrWurstParseTreeTransformer.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,12 @@ private Arguments transformArgumentList(ArgumentListContext al) {
10271027
private ExprMemberMethod transformMemberMethodCall2(WPos source,
10281028
ExprContext receiver, Token dots, Token funcName,
10291029
TypeArgsContext typeArgs, ArgumentListContext args) {
1030-
Expr left = transformExpr(receiver);
1030+
return transformMemberMethodCall2(source, transformExpr(receiver), dots, funcName, typeArgs, args);
1031+
}
1032+
1033+
private ExprMemberMethod transformMemberMethodCall2(WPos source,
1034+
Expr left, Token dots, Token funcName,
1035+
TypeArgsContext typeArgs, ArgumentListContext args) {
10311036
if (dots.getType() == WurstParser.DOT) {
10321037
return Ast.ExprMemberMethodDot(source, left, text(funcName),
10331038
transformTypeArgs(typeArgs), transformArgumentList(args));
@@ -1091,6 +1096,11 @@ private Expr transformExpr(ExprContext e) {
10911096
} else if (e.castToType != null) {
10921097
return Ast.ExprCast(source, transformTypeExpr(e.castToType),
10931098
transformExpr(e.left));
1099+
} else if (e.dotsTypeCall != null) {
1100+
TypeExpr receiverType = transformGenericTypeReceiver(e.receiverType);
1101+
Expr left = Ast.ExprTypeRef(receiverType.getSource(), receiverType);
1102+
return transformMemberMethodCall2(source, left, e.dotsTypeCall,
1103+
e.typeFuncName, e.typeCallTypeArgs, e.typeCallArgs);
10941104
} else if (e.dotsVar != null) {
10951105
return transformExprMemberVarAccess2(source, e.receiver, e.dotsVar,
10961106
e.varName, e.indexes());
@@ -1120,6 +1130,23 @@ private Expr transformExpr(ExprContext e) {
11201130

11211131
}
11221132

1133+
private TypeExpr transformGenericTypeReceiver(GenericTypeReceiverContext receiverType) {
1134+
OptTypeExpr scopeType = Ast.NoTypeExpr();
1135+
TypeExpr result = null;
1136+
1137+
for (GenericTypeReceiverPrefixPartContext part : receiverType.receiverTypePrefixes) {
1138+
result = Ast.TypeExprSimple(source(part.typeName), scopeType,
1139+
part.typeName.getText(), Ast.TypeExprList());
1140+
scopeType = result;
1141+
}
1142+
1143+
GenericTypeReceiverGenericPartContext genericPart = receiverType.receiverTypeGenericPart;
1144+
result = Ast.TypeExprSimple(source(genericPart.typeName), scopeType,
1145+
genericPart.typeName.getText(), transformTypeArgs(genericPart.typeArgsNonEmpty()));
1146+
1147+
return result;
1148+
}
1149+
11231150
private int beginPos(ParseTree left) {
11241151
if (left instanceof ParserRuleContext) {
11251152
ParserRuleContext left2 = (ParserRuleContext) left;
@@ -1379,6 +1406,14 @@ private TypeExprList transformTypeArgs(TypeArgsContext typeArgs) {
13791406
return result;
13801407
}
13811408

1409+
private TypeExprList transformTypeArgs(TypeArgsNonEmptyContext typeArgs) {
1410+
TypeExprList result = Ast.TypeExprList();
1411+
for (TypeExprContext e : typeArgs.args) {
1412+
result.add(transformTypeExpr(e));
1413+
}
1414+
return result;
1415+
}
1416+
13821417
private WParameters transformFormalParameters(FormalParametersContext ps,
13831418
boolean makeConstant) {
13841419
WParameters result = Ast.WParameters();

0 commit comments

Comments
 (0)