Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions de.peeeq.wurstscript/parserspec/wurstscript.parseq
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ Expr =
| ExprMember
| ExprFunctionCall(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Identifier funcNameId, TypeExprList typeArgs, Arguments args)
| ExprNewObject(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Identifier typeNameId, TypeExprList typeArgs, Arguments args)
| ExprTypeRef(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ)
| ExprCast(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ, Expr expr)
| ExprInstanceOf(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ, Expr expr)
| ExprClosure(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, @ignoreForEquality de.peeeq.wurstscript.parser.WPos arrowSource, WShortParameters shortParameters, Expr implementation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ indexes:


expr:
exprPrimary
receiverTypeName=ID receiverTypeTypeArgs=typeArgsNonEmpty dotsTypeCall=('.'|'..') typeFuncName=ID? typeCallTypeArgs=typeArgs typeCallArgs=argumentList
Comment thread
Frotty marked this conversation as resolved.
Outdated
| exprPrimary
| left=expr 'castTo' castToType=typeExpr
| left=expr 'instanceof' instaneofType=typeExpr
| receiver=expr dotsCall=('.'|'..') funcName=ID? typeArgs argumentList
Expand Down Expand Up @@ -443,6 +444,8 @@ stmtSkip:'skip';

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

typeArgsNonEmpty: '<' args+=typeExpr (',' args+=typeExpr)* '>';

exprList : exprs+=expr (',' exprs+=expr)*;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,11 @@ public List<Either<String, MarkedString>> case_TypeExprSimple(TypeExprSimple t)
return typeExpr(t);
}

@Override
public List<Either<String, MarkedString>> case_ExprTypeRef(ExprTypeRef e) {
return typeExpr(e.getTyp());
}

@Override
public List<Either<String, MarkedString>> case_Modifiers(Modifiers modifiers) {
return string("Modifiers for this declaration.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public static WurstType calculate(ExprFuncRef term) {
return WurstTypeCode.instance();
}

public static WurstType calculate(ExprTypeRef term) {
return term.getTyp().attrTyp();
}


public static WurstType calculate(ExprVarAccess term) {
NameLink varDef = term.attrNameLink();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ public static String description(ExprThis e) {
return "this has type " + htmlType(e.attrTyp());
}

public static String description(ExprTypeRef e) {
return "Type reference " + htmlType(e.attrTyp());
}

public static String description(ExprTypeId exprTypeId) {
return "typeId: returns the typeId of an object or class. The typeId is "
+ "a unique number for each class in the same type hierarchy.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ public static ImmutableList<NameDef> calculate(ExprFuncRef exprFuncRef) {
return ImmutableList.emptyList();
}

public static ImmutableList<NameDef> calculate(ExprTypeRef exprTypeRef) {
return ImmutableList.emptyList();
}

public static ImmutableList<NameDef> calculate(ExprTypeId e) {
return e.getLeft().attrReadVariables();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,10 @@ public static void prettyPrint(ExprThis e, Spacer spacer, StringBuilder sb, int
sb.append("this");
}

public static void prettyPrint(ExprTypeRef e, Spacer spacer, StringBuilder sb, int indent) {
e.getTyp().prettyPrint(spacer, sb, indent);
}

public static void prettyPrint(ExprTypeId e, Spacer spacer, StringBuilder sb, int indent) {
e.getLeft().prettyPrint(spacer, sb, indent);
sb.append(".typeId");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import de.peeeq.wurstio.jassinterpreter.VarargArray;
import de.peeeq.wurstscript.WLogger;
import de.peeeq.wurstscript.ast.Annotation;
import de.peeeq.wurstscript.ast.ClassOrInterface;
import de.peeeq.wurstscript.ast.FuncDef;
import de.peeeq.wurstscript.ast.HasModifier;
import de.peeeq.wurstscript.ast.Modifier;
import de.peeeq.wurstscript.gui.WurstGui;
Expand Down Expand Up @@ -172,6 +174,15 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
subst.put(fvars.get(i2), targs.get(i2).getType());
}

ImClass sourceOwner = findSourceOwnerClass(f, globalState.getProg());
if (sourceOwner != null) {
ImTypeVars cvars = sourceOwner.getTypeVariables();
int n2 = Math.min(cvars.size(), targs.size());
for (int i2 = 0; i2 < n2; i2++) {
subst.put(cvars.get(i2), targs.get(i2).getType());
}
}

// 2) If the function is inside a class, also bind class type vars with the same call type args
Element owner = f.getParent();
while (owner != null && !(owner instanceof ImClass)) {
Expand Down Expand Up @@ -249,6 +260,26 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
}
}

private static @Nullable ImClass findSourceOwnerClass(ImFunction f, ImProg prog) {
if (!(f.getTrace() instanceof FuncDef)) {
return null;
}
FuncDef fd = (FuncDef) f.getTrace();
if (!fd.attrIsStatic()) {
return null;
}
ClassOrInterface owner = fd.attrNearestClassOrInterface();
if (owner == null) {
return null;
}
for (ImClass c : prog.getClasses()) {
if (c.getTrace() == owner) {
return c;
}
}
return null;
}


public static de.peeeq.wurstscript.ast.Element getTrace(ProgramState globalState, ImFunction f) {
Element lastStatement = globalState.getLastStatement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,12 @@ private Arguments transformArgumentList(ArgumentListContext al) {
private ExprMemberMethod transformMemberMethodCall2(WPos source,
ExprContext receiver, Token dots, Token funcName,
TypeArgsContext typeArgs, ArgumentListContext args) {
Expr left = transformExpr(receiver);
return transformMemberMethodCall2(source, transformExpr(receiver), dots, funcName, typeArgs, args);
}

private ExprMemberMethod transformMemberMethodCall2(WPos source,
Expr left, Token dots, Token funcName,
TypeArgsContext typeArgs, ArgumentListContext args) {
if (dots.getType() == WurstParser.DOT) {
return Ast.ExprMemberMethodDot(source, left, text(funcName),
transformTypeArgs(typeArgs), transformArgumentList(args));
Expand Down Expand Up @@ -1091,6 +1096,12 @@ private Expr transformExpr(ExprContext e) {
} else if (e.castToType != null) {
return Ast.ExprCast(source, transformTypeExpr(e.castToType),
transformExpr(e.left));
} else if (e.dotsTypeCall != null) {
TypeExpr receiverType = Ast.TypeExprSimple(source(e.receiverTypeName),
Ast.NoTypeExpr(), e.receiverTypeName.getText(), transformTypeArgs(e.receiverTypeTypeArgs));
Expr left = Ast.ExprTypeRef(receiverType.getSource(), receiverType);
return transformMemberMethodCall2(source, left, e.dotsTypeCall,
e.typeFuncName, e.typeCallTypeArgs, e.typeCallArgs);
} else if (e.dotsVar != null) {
return transformExprMemberVarAccess2(source, e.receiver, e.dotsVar,
e.varName, e.indexes());
Expand Down Expand Up @@ -1379,6 +1390,14 @@ private TypeExprList transformTypeArgs(TypeArgsContext typeArgs) {
return result;
}

private TypeExprList transformTypeArgs(TypeArgsNonEmptyContext typeArgs) {
TypeExprList result = Ast.TypeExprList();
for (TypeExprContext e : typeArgs.args) {
result.add(transformTypeExpr(e));
}
return result;
}

private WParameters transformFormalParameters(FormalParametersContext ps,
boolean makeConstant) {
WParameters result = Ast.WParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ public static ImExpr translate(ExprNewObject e, ImTranslator t, ImFunction f) {
return wrapTranslation(e, t, translateIntern(e, t, f));
}

public static ImExpr translate(ExprTypeRef e, ImTranslator t, ImFunction f) {
throw new CompileError(e, "Type reference " + Utils.printTypeExpr(e.getTyp()) + " cannot be used as a value.");
}

public static ImExpr translate(ExprInstanceOf e, ImTranslator t, ImFunction f) {
return wrapTranslation(e, t, translateIntern(e, t, f));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ public void popContinueFlag() {
return continueFlagStack.peek();
}

public Map<TypeParamDef, ImTypeVar> getTypeVarOverridesForFunction(ImFunction f) {
Map<TypeParamDef, ImTypeVar> result = new IdentityHashMap<>();
for (ImTypeVar tv : f.getTypeVariables()) {
TypeParamDef tp = typeVariableReverse.get(tv);
if (tp != null) {
result.put(tp, tv);
}
}
return result;
}


public ImTranslator(WurstModel wurstProg, boolean isUnitTestMode, RunArgs runArgs) {
this.wurstProg = wurstProg;
Expand Down Expand Up @@ -930,7 +941,13 @@ public ImFunction getFuncFor(TranslatedToImFunction funcDef) {

ImTypeVars typeVars = collectTypeVarsForFunction(funcDef);
ImFunction f = ImFunction(funcDef, name, typeVars, ImVars(), ImVoid(), ImVars(), ImStmts(), flags);
funcDef.imCreateFuncSkeleton(this, f);
Map<TypeParamDef, ImTypeVar> ov = getTypeVarOverridesForFunction(f);
pushTypeVarOverrides(ov);
try {
funcDef.imCreateFuncSkeleton(this, f);
} finally {
popTypeVarOverrides(ov);
}

addFunction(f, funcDef);
functionMap.put(funcDef, f);
Expand Down Expand Up @@ -992,6 +1009,12 @@ private ImTypeVars collectTypeVarsForFunction(TranslatedToImFunction funcDef) {
funcDef.match(new TranslatedToImFunction.MatcherVoid() {
@Override
public void case_FuncDef(FuncDef funcDef) {
if (funcDef.attrIsStatic()) {
ClassOrInterface owner = funcDef.attrNearestClassOrInterface();
if (owner != null) {
handleTypeParameters(owner.getTypeParameters());
}
}
handleTypeParameters(funcDef.getTypeParameters());
}

Expand All @@ -1004,7 +1027,13 @@ private void handleTypeParameters(TypeParamDefs tps) {

private void handleTypeParameter(TypeParamDef tp) {
if (tp.getTypeParamConstraints() instanceof TypeExprList) {
typeVars.add(typeVariable.getFor(tp));
ImTypeVar base = typeVariable.getFor(tp);
if (hasTypeVarNamed(typeVars, base.getName())) {
return;
Comment thread
Frotty marked this conversation as resolved.
Outdated
}
ImTypeVar v = JassIm.ImTypeVar(base.getName());
typeVariableReverse.put(v, tp);
typeVars.add(v);
}
}

Expand Down Expand Up @@ -1172,7 +1201,14 @@ public int getTupleIndex(TupleDef tupleDef, VarDef parameter) {
public ImVar getVarFor(VarDef varDef) {
ImVar v = varMap.get(varDef);
if (v == null) {
ImType type = varDef.attrTyp().imTranslateType(this);
Map<TypeParamDef, ImTypeVar> ov = getOwnerTypeVarOverridesForStaticClassVar(varDef);
pushTypeVarOverrides(ov);
ImType type;
try {
type = varDef.attrTyp().imTranslateType(this);
} finally {
popTypeVarOverrides(ov);
}
String name = varDef.getName();
if (isNamedScopeVar(varDef)) {
name = getNameFor(varDef.attrNearestNamedScope()) + "_" + name;
Expand All @@ -1184,6 +1220,25 @@ public ImVar getVarFor(VarDef varDef) {
return v;
}

private Map<TypeParamDef, ImTypeVar> getOwnerTypeVarOverridesForStaticClassVar(VarDef varDef) {
if (!(varDef instanceof GlobalVarDef) || !varDef.attrIsStatic()) {
return Collections.emptyMap();
}
ClassOrInterface owner = varDef.attrNearestClassOrInterface();
if (owner == null) {
return Collections.emptyMap();
}
Map<TypeParamDef, ImTypeVar> result = new IdentityHashMap<>();
if (owner instanceof AstElementWithTypeParameters) {
for (TypeParamDef tp : ((AstElementWithTypeParameters) owner).getTypeParameters()) {
if (tp.getTypeParamConstraints() instanceof TypeExprList) {
result.put(tp, typeVariable.getFor(tp));
}
}
}
return result;
}

private boolean isNamedScopeVar(VarDef varDef) {
if (varDef.getParent() == null) {
return false;
Expand Down Expand Up @@ -1217,10 +1272,16 @@ public void setTranslated(ClassDef c) {

public List<ImStmt> translateStatements(ImFunction f, List<WStatement> statements) {
List<ImStmt> result = Lists.newArrayList();
for (WStatement s : statements) {
lasttranslatedThing = s;
ImStmt translated = s.imTranslateStmt(this, f);
result.add(translated);
Map<TypeParamDef, ImTypeVar> ov = getTypeVarOverridesForFunction(f);
pushTypeVarOverrides(ov);
try {
for (WStatement s : statements) {
lasttranslatedThing = s;
ImStmt translated = s.imTranslateStmt(this, f);
result.add(translated);
}
} finally {
popTypeVarOverrides(ov);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,32 @@ public void genericStaticArray_instanceMethods_runtime() {
);
}

@Test
public void genericStaticArray_staticMethods_specializedTypeReceiver_runtime() {
testAssertOkLines(true,
"package test",
" native testSuccess()",
" class Box<T:>",
" private static T array store",
" static function put(int i, T v)",
" store[i] = v",
" static function get(int i) returns T",
" return store[i]",
" static function getFirst() returns T",
" return get(1)",
" static function same(T v) returns T",
" return v",
" init",
" Box<int>.put(1, 42)",
" Box<int>.put(2, 7)",
" Box<real>.put(1, 1.5)",
" Box<real>.put(2, 2.5)",
" if Box<int>.get(1) == 42 and Box<int>.get(2) == 7 and Box<int>.getFirst() == 42 and Box<int>.same(13) == 13 and Box<real>.get(1) == 1.5 and Box<real>.get(2) == 2.5 and Box<real>.getFirst() == 1.5 and Box<real>.same(3.5) == 3.5",
" testSuccess()",
"endpackage"
);
}

@Test
public void genericStaticTuple_runtime() {
testAssertOkLines(true,
Expand Down
Loading