Skip to content

Commit 1b37043

Browse files
committed
Capture tuple operands before comparison
1 parent e415c71 commit 1b37043

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

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

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ private static void removeTupleExprs(int posHint, Element elem, ImTranslator tra
515515
ImExprs exprs = (ImExprs) elem;
516516
if (exprs.getParent() instanceof ImOperatorCall) {
517517
ImOperatorCall opCall = (ImOperatorCall) exprs.getParent();
518-
handleTupleInOpCall(replacer, opCall);
518+
handleTupleInOpCall(replacer, opCall, f);
519519
return;
520520
} else {
521521
// in function arguments, other tuples
@@ -548,20 +548,25 @@ private static void removeTupleExprs(int posHint, Element elem, ImTranslator tra
548548

549549
}
550550

551-
private static void handleTupleInOpCall(Replacer replacer, ImOperatorCall opCall) {
551+
private static void handleTupleInOpCall(Replacer replacer, ImOperatorCall opCall, ImFunction f) {
552552
if (opCall.getParent() == null) {
553553
throw new RuntimeException("opCall not used: " + opCall);
554554
}
555555
ImTupleExpr left = (ImTupleExpr) opCall.getArguments().get(0);
556556
ImTupleExpr right = (ImTupleExpr) opCall.getArguments().get(1);
557557
WurstOperator op = opCall.getOp();
558558

559+
ImStmts evaluation = JassIm.ImStmts();
560+
List<ImExpr> leftComponents = captureTupleComponents(left, evaluation, f);
561+
List<ImExpr> rightComponents = captureTupleComponents(right, evaluation, f);
562+
if (leftComponents.size() != rightComponents.size()) {
563+
throw new CompileError(opCall.attrTrace(), "Cannot compare tuples with different arity.");
564+
}
565+
559566
List<ImExpr> componentComparisons = new ArrayList<>();
560-
for (int i = 0; i < left.getExprs().size(); i++) {
561-
ImExpr l = left.getExprs().get(i);
562-
ImExpr r = right.getExprs().get(i);
563-
l.setParent(null);
564-
r.setParent(null);
567+
for (int i = 0; i < leftComponents.size(); i++) {
568+
ImExpr l = leftComponents.get(i);
569+
ImExpr r = rightComponents.get(i);
565570
componentComparisons.add(JassIm.ImOperatorCall(op, JassIm.ImExprs(l, r)));
566571
}
567572

@@ -598,7 +603,21 @@ private static void handleTupleInOpCall(Replacer replacer, ImOperatorCall opCall
598603
newExpr = (seen ? Optional.of(acc) : Optional.<ImExpr>empty())
599604
.get();
600605
}
601-
replacer.replace(opCall, newExpr);
606+
replacer.replace(opCall, JassIm.ImStatementExpr(evaluation, newExpr));
607+
}
608+
609+
private static List<ImExpr> captureTupleComponents(ImTupleExpr tuple, ImStmts evaluation, ImFunction f) {
610+
List<ImExpr> components = new ArrayList<>();
611+
List<ImExpr> flat = new ArrayList<>();
612+
flattenTupleExpr(tuple, evaluation, flat);
613+
for (ImExpr expr : flat) {
614+
expr.setParent(null);
615+
ImVar temp = JassIm.ImVar(expr.attrTrace(), expr.attrTyp(), "tuple_compare", false);
616+
f.getLocals().add(temp);
617+
evaluation.add(JassIm.ImSet(expr.attrTrace(), JassIm.ImVarAccess(temp), expr));
618+
components.add(JassIm.ImVarAccess(temp));
619+
}
620+
return components;
602621
}
603622

604623
private static ImStatementExpr inSet(ImSet imSet, ImTranslator translator, ImFunction f) {

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaBackendAuditTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,24 @@ public void tupleReturnSlotsAreSharedAcrossMultipleInterfaceRoots() throws IOExc
151151
assertFalse(compiled.contains("tupleEquals"));
152152
}
153153

154+
@Test
155+
public void tupleReturningCallsAreCapturedBeforeComparison() throws IOException {
156+
test().testLua(true).executeProg().lines(
157+
"package Test",
158+
"native testSuccess()",
159+
"tuple pair(int x, int y)",
160+
"@noinline function value(int seed) returns pair",
161+
" return pair(0, seed)",
162+
"init",
163+
" if value(1) != value(2) and not (value(1) == value(2))",
164+
" testSuccess()"
165+
);
166+
167+
String compiled = compiledLua("tupleReturningCallsAreCapturedBeforeComparison");
168+
assertFalse(compiled.contains("tupleCopy"));
169+
assertFalse(compiled.contains("tupleEquals"));
170+
}
171+
154172
@Test
155173
public void compiletimeGenericArrayReplayLeavesAreSplit() {
156174
String compiled = compileLuaWithRunArgs(

0 commit comments

Comments
 (0)