Skip to content

Commit 7f25b41

Browse files
authored
Optimize Lua type assurance boundaries (#1280)
1 parent bea567a commit 7f25b41

9 files changed

Lines changed: 800 additions & 85 deletions

File tree

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

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import de.peeeq.wurstscript.WLogger;
44
import de.peeeq.wurstscript.ast.*;
5+
import de.peeeq.wurstscript.attributes.names.FuncLink;
56
import de.peeeq.wurstscript.types.*;
67
import de.peeeq.wurstscript.utils.Utils;
78
import org.eclipse.jdt.annotation.NonNull;
@@ -46,6 +47,14 @@ public class AttrExprExpectedType {
4647
return varDef.attrTyp();
4748
} else if (parent instanceof ExprBinary) {
4849
ExprBinary exprBinary = (ExprBinary) parent;
50+
if (exprBinary.attrFuncLink() != null) {
51+
FunctionSignature signature = FunctionSignature.fromNameLink(exprBinary.attrFuncLink());
52+
if (exprBinary.getLeft() == expr && signature.getReceiverType() != null) {
53+
return signature.getReceiverType();
54+
} else if (exprBinary.getRight() == expr && !signature.getParamTypes().isEmpty()) {
55+
return signature.getParamType(0);
56+
}
57+
}
4958
WurstType leftType = exprBinary.getLeft().attrTyp();
5059
WurstType rightType = exprBinary.getRight().attrTyp();
5160
if (leftType.equalsType(rightType, expr)) {
@@ -72,10 +81,44 @@ public class AttrExprExpectedType {
7281
}
7382
} else if (parent instanceof StmtReturn) {
7483
StmtReturn stmtReturn = (StmtReturn) parent;
84+
if (stmtReturn.getParent() instanceof ExprStatementsBlock) {
85+
ExprStatementsBlock block = (ExprStatementsBlock) stmtReturn.getParent();
86+
WurstType expectedType = block.attrExpectedTypRaw();
87+
if (expectedType instanceof WurstTypeUnknown
88+
&& block.getParent() instanceof ExprClosure) {
89+
FuncLink abstractMethod = ((ExprClosure) block.getParent()).attrClosureAbstractMethod();
90+
if (abstractMethod != null) {
91+
return abstractMethod.getReturnType();
92+
}
93+
}
94+
return expectedType;
95+
}
7596
FunctionImplementation nearestFuncDef = stmtReturn.attrNearestFuncDef();
7697
if (nearestFuncDef != null) {
7798
return nearestFuncDef.attrReturnTyp();
7899
}
100+
} else if (parent instanceof StmtForRange) {
101+
StmtForRange forRange = (StmtForRange) parent;
102+
if (forRange.getTo() == expr || forRange.getStep() == expr) {
103+
return WurstTypeInt.instance();
104+
}
105+
} else if (parent instanceof ExprStatementsBlock) {
106+
ExprStatementsBlock block = (ExprStatementsBlock) parent;
107+
if (block.getReturnStmt() != null && block.getReturnStmt().getReturnedObj() == expr) {
108+
return block.attrExpectedTypRaw();
109+
}
110+
} else if (parent instanceof Indexes) {
111+
return WurstTypeInt.instance();
112+
} else if (parent instanceof SwitchStmt) {
113+
SwitchStmt switchStmt = (SwitchStmt) parent;
114+
if (switchStmt.getExpr() == expr) {
115+
for (SwitchCase switchCase : switchStmt.getCases()) {
116+
for (Expr caseExpr : switchCase.getExpressions()) {
117+
WurstType type = caseExpr.attrTyp();
118+
return type instanceof WurstTypeIntLiteral ? WurstTypeInt.instance() : type;
119+
}
120+
}
121+
}
79122
} else if (parent instanceof SwitchCase) {
80123
SwitchCase sc = (SwitchCase) parent;
81124
SwitchStmt s = (SwitchStmt) sc.getParent().getParent();
@@ -110,6 +153,14 @@ public class AttrExprExpectedType {
110153

111154
private static WurstType expectedTypeSuperCall(SuperConstructorCall sc, Expr expr) {
112155
ConstructorDef constr = (ConstructorDef) sc.getParent();
156+
int paramIndex = SmallHelpers.superArgs(constr).indexOf(expr);
157+
ConstructorDef selected = constr.attrSuperConstructor();
158+
if (selected != null) {
159+
WurstType selectedType = constructorParameterType(selected, paramIndex);
160+
if (!(selectedType instanceof WurstTypeUnknown)) {
161+
return selectedType;
162+
}
163+
}
113164
ClassDef c = constr.attrNearestClassDef();
114165
if (c == null) {
115166
return WurstTypeUnknown.instance();
@@ -125,8 +176,6 @@ private static WurstType expectedTypeSuperCall(SuperConstructorCall sc, Expr exp
125176

126177
WurstType res = WurstTypeUnknown.instance();
127178

128-
int paramIndex = SmallHelpers.superArgs(constr).indexOf(expr);
129-
130179
for (ConstructorDef superConstr : constructors) {
131180
if (superConstr.getParameters().size() == SmallHelpers.superArgs(constr).size()) {
132181
res = res.typeUnion(superConstr.getParameters().get(paramIndex).getTyp().attrTyp(), expr);
@@ -136,6 +185,19 @@ private static WurstType expectedTypeSuperCall(SuperConstructorCall sc, Expr exp
136185
return res;
137186
}
138187

188+
public static WurstType constructorParameterType(ConstructorDef constructor, int argumentIndex) {
189+
if (argumentIndex < 0 || constructor.getParameters().isEmpty()) {
190+
return WurstTypeUnknown.instance();
191+
}
192+
int lastParameterIndex = constructor.getParameters().size() - 1;
193+
WurstType parameterType = constructor.getParameters()
194+
.get(Math.min(argumentIndex, lastParameterIndex)).attrTyp();
195+
if (argumentIndex >= lastParameterIndex && parameterType instanceof WurstTypeVararg) {
196+
return ((WurstTypeVararg) parameterType).getBaseType();
197+
}
198+
return argumentIndex <= lastParameterIndex ? parameterType : WurstTypeUnknown.instance();
199+
}
200+
139201
private static WurstType expectedType(Expr expr, Arguments args, StmtCall stmtCall) {
140202
Collection<FunctionSignature> sigs = stmtCall.attrPossibleFunctionSignatures();
141203

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ClassTranslator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import de.peeeq.wurstscript.ast.*;
44
import de.peeeq.wurstscript.ast.Element;
5+
import de.peeeq.wurstscript.attributes.AttrExprExpectedType;
56
import de.peeeq.wurstscript.attributes.OverloadingResolver;
67
import de.peeeq.wurstscript.jassIm.Element.DefaultVisitor;
78
import de.peeeq.wurstscript.jassIm.*;
@@ -400,8 +401,11 @@ private void createConstructFunc(ConstructorDef constr) {
400401
if (calledConstr != null && calledConstr != constr) {
401402
ImFunction calledConstrFunc = translator.getConstructFunc(calledConstr);
402403
ImExprs arguments = ImExprs(ImVarAccess(thisVar));
403-
for (Expr a : thisCall.getArgs()) {
404-
arguments.add(a.imTranslateExpr(translator, f));
404+
for (int i = 0; i < thisCall.getArgs().size(); i++) {
405+
Expr argument = thisCall.getArgs().get(i);
406+
WurstType expectedType = AttrExprExpectedType.constructorParameterType(calledConstr, i);
407+
arguments.add(ExprTranslation.translateWithExpectedType(
408+
argument, translator, f, expectedType));
405409
}
406410
f.getBody().add(ImFunctionCall(trace, calledConstrFunc, classTypeArgs(), arguments, false, CallType.NORMAL));
407411
bodyStartIndex = firstRelevantIndex + 1;

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ClosureTranslator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,16 @@ private ImClass createClass() {
201201
OverrideUtils.addOverrideClosure(tr, superMethod, m, e);
202202

203203

204-
ImExpr translated = e.getImplementation().imTranslateExpr(tr, impl);
204+
ImExpr translated;
205+
boolean propagatesExpectedType = ExprTranslation.isCompositeExpectedTypeExpression(e.getImplementation());
206+
if (propagatesExpectedType) {
207+
translated = ExprTranslation.translateWithExpectedType(
208+
e.getImplementation(), tr, impl, superMethod.attrReturnType());
209+
} else {
210+
translated = e.getImplementation().imTranslateExpr(tr, impl);
211+
translated = ExprTranslation.wrapTranslation(e.getImplementation(), tr, translated,
212+
e.getImplementation().attrTypRaw(), superMethod.attrReturnType());
213+
}
205214

206215

207216
if (e.getImplementation().attrTyp().isVoid()) {

0 commit comments

Comments
 (0)