Skip to content

Commit 2c1e7b9

Browse files
committed
many more lua fixes
1 parent 4d8881a commit 2c1e7b9

6 files changed

Lines changed: 127 additions & 35 deletions

File tree

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import de.peeeq.wurstscript.translation.imtojass.ImAttrType;
2929
import de.peeeq.wurstscript.translation.imtojass.ImToJassTranslator;
3030
import de.peeeq.wurstscript.translation.imtranslation.*;
31+
import de.peeeq.wurstscript.translation.lua.translation.RemoveGarbage;
3132
import de.peeeq.wurstscript.translation.lua.translation.LuaTranslator;
3233
import de.peeeq.wurstscript.types.TypesHelper;
3334
import de.peeeq.wurstscript.utils.LineOffsets;
@@ -937,7 +938,12 @@ public LuaCompilationUnit transformProgToLua() {
937938
printDebugImProg("./test-output/lua/im " + stage++ + "_afteroptimize.im");
938939
timeTaker.endPhase();
939940
}
940-
beginPhase(13, "translate to lua");
941+
beginPhase(13, "lua remove garbage");
942+
RemoveGarbage.removeGarbage(imProg);
943+
imProg.flatten(imTranslator);
944+
timeTaker.endPhase();
945+
946+
beginPhase(14, "translate to lua");
941947
LuaTranslator luaTranslator = new LuaTranslator(imProg, imTranslator);
942948
LuaCompilationUnit luaCode = luaTranslator.translate();
943949
ImAttrType.setWurstClassType(TypesHelper.imInt());

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ public ImType case_ImTypeVarRef(ImTypeVarRef t) {
288288
*/
289289
private void transformTranslated(ImExpr t) {
290290
final List<ImVarAccess> vas = Lists.newArrayList();
291+
final List<ImVarAccess> thisVarAccessesToRewrite = Lists.newArrayList();
291292
final List<ImMemberAccess> receiversToRewrite = Lists.newArrayList();
292293
ImVar closureThisVar = tr.getThisVar(e);
293294

@@ -297,6 +298,14 @@ public void visit(ImVarAccess va) {
297298
super.visit(va);
298299
if (isLocalToOtherFunc(va.getVar())) {
299300
vas.add(va);
301+
return;
302+
}
303+
if (capturedThisField != null && va.getVar() == closureThisVar) {
304+
// Explicit `this` used inside a closure (e.g. "var cur = this")
305+
// must refer to captured outer this, not the synthetic closure instance.
306+
if (!isReceiverInMemberAccess(va)) {
307+
thisVarAccessesToRewrite.add(va);
308+
}
300309
}
301310
}
302311

@@ -318,11 +327,22 @@ public void visit(ImMemberAccess ma) {
318327
va.replaceBy(JassIm.ImMemberAccess(e, closureThis(), JassIm.ImTypeArguments(), v, JassIm.ImExprs()));
319328
}
320329

330+
for (ImVarAccess va : thisVarAccessesToRewrite) {
331+
va.replaceBy(JassIm.ImMemberAccess(e, closureThis(), JassIm.ImTypeArguments(), capturedThisField, JassIm.ImExprs()));
332+
}
333+
321334
for (ImMemberAccess ma : receiversToRewrite) {
322335
ma.setReceiver(JassIm.ImMemberAccess(e, closureThis(), JassIm.ImTypeArguments(), capturedThisField, JassIm.ImExprs()));
323336
}
324337
}
325338

339+
private boolean isReceiverInMemberAccess(ImVarAccess va) {
340+
if (va.getParent() instanceof ImMemberAccess ma) {
341+
return ma.getReceiver() == va;
342+
}
343+
return false;
344+
}
345+
326346
private void captureEnclosingThis() {
327347
ImVar outerThis = getEnclosingThisVar();
328348
if (outerThis != null) {

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/ExprTranslation.java

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,6 @@ public static LuaExpr translate(ImOperatorCall e, LuaTranslator tr) {
183183
LuaExpr leftExpr = left.translateToLua(tr);
184184
LuaExpr rightExpr = right.translateToLua(tr);
185185
LuaOpBinary op;
186-
if (isIntNumericOperator(e.getOp())) {
187-
leftExpr = ensureInt(leftExpr, tr);
188-
rightExpr = ensureInt(rightExpr, tr);
189-
} else if (isRealNumericOperator(e.getOp())) {
190-
leftExpr = ensureReal(leftExpr, tr);
191-
rightExpr = ensureReal(rightExpr, tr);
192-
}
193186
if (e.getOp() == WurstOperator.MOD_INT) {
194187
op = LuaAst.LuaOpMod();
195188

@@ -214,7 +207,6 @@ public static LuaExpr translate(ImOperatorCall e, LuaTranslator tr) {
214207
break;
215208
case UNARY_MINUS:
216209
op = LuaAst.LuaOpMinus();
217-
argT = ensureReal(argT, tr);
218210
break;
219211
default:
220212
throw new Error("not implemented: unary operator " + e.getOp());
@@ -225,29 +217,6 @@ public static LuaExpr translate(ImOperatorCall e, LuaTranslator tr) {
225217
throw new Error("not implemented: " + e);
226218
}
227219

228-
private static boolean isIntNumericOperator(WurstOperator op) {
229-
return op == WurstOperator.DIV_INT || op == WurstOperator.MOD_INT;
230-
}
231-
232-
private static boolean isRealNumericOperator(WurstOperator op) {
233-
return op == WurstOperator.LESS
234-
|| op == WurstOperator.LESS_EQ
235-
|| op == WurstOperator.GREATER
236-
|| op == WurstOperator.GREATER_EQ
237-
|| op == WurstOperator.MINUS
238-
|| op == WurstOperator.MULT
239-
|| op == WurstOperator.DIV_REAL
240-
|| op == WurstOperator.MOD_REAL;
241-
}
242-
243-
private static LuaExpr ensureInt(LuaExpr expr, LuaTranslator tr) {
244-
return LuaAst.LuaExprFunctionCall(tr.ensureIntFunction, LuaAst.LuaExprlist(expr));
245-
}
246-
247-
private static LuaExpr ensureReal(LuaExpr expr, LuaTranslator tr) {
248-
return LuaAst.LuaExprFunctionCall(tr.ensureRealFunction, LuaAst.LuaExprlist(expr));
249-
}
250-
251220
static class TupleFunc {
252221
final ImTupleType tupleType;
253222
final LuaFunction func;
@@ -403,13 +372,34 @@ public static LuaExpr translate(ImVarAccess e, LuaTranslator tr) {
403372
}
404373

405374
public static LuaExpr translate(ImVarArrayAccess e, LuaTranslator tr) {
375+
LuaExpr access = translateArrayAccessRaw(e, tr);
376+
return ensureByType(access, e.attrTyp(), tr);
377+
}
378+
379+
public static LuaExpr translateArrayAccessRaw(ImVarArrayAccess e, LuaTranslator tr) {
406380
LuaExprlist indexes = LuaAst.LuaExprlist();
407381
for (ImExpr ie : e.getIndexes()) {
408382
indexes.add(ie.translateToLua(tr));
409383
}
410384
return LuaAst.LuaExprArrayAccess(LuaAst.LuaExprVarAccess(tr.luaVar.getFor(e.getVar())), indexes);
411385
}
412386

387+
private static LuaExpr ensureByType(LuaExpr expr, ImType type, LuaTranslator tr) {
388+
if (TypesHelper.isStringType(type)) {
389+
return LuaAst.LuaExprFunctionCall(tr.ensureStrFunction, LuaAst.LuaExprlist(expr));
390+
}
391+
if (TypesHelper.isIntType(type)) {
392+
return LuaAst.LuaExprFunctionCall(tr.ensureIntFunction, LuaAst.LuaExprlist(expr));
393+
}
394+
if (TypesHelper.isBoolType(type)) {
395+
return LuaAst.LuaExprFunctionCall(tr.ensureBoolFunction, LuaAst.LuaExprlist(expr));
396+
}
397+
if (TypesHelper.isRealType(type)) {
398+
return LuaAst.LuaExprFunctionCall(tr.ensureRealFunction, LuaAst.LuaExprlist(expr));
399+
}
400+
return expr;
401+
}
402+
413403
public static LuaExpr translate(ImGetStackTrace e, LuaTranslator tr) {
414404
// return LuaAst.LuaLiteral("debug.traceback()");
415405
return LuaAst.LuaLiteral("\"$Stacktrace$\"");

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,8 @@ public LuaExpr case_ImSimpleType(ImSimpleType st) {
918918
return LuaAst.LuaExprBoolVal(false);
919919
} else if (TypesHelper.isRealType(st)) {
920920
return LuaAst.LuaExprRealVal("0.");
921+
} else if (TypesHelper.isStringType(st)) {
922+
return LuaAst.LuaExprStringVal("");
921923
}
922924
return LuaAst.LuaExprNull();
923925
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/StmtTranslation.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ public static void translate(ImReturn s, List<LuaStatement> res, LuaTranslator t
3434
}
3535

3636
public static void translate(ImSet s, List<LuaStatement> res, LuaTranslator tr) {
37-
LuaExpr left = s.getLeft().translateToLua(tr);
37+
LuaExpr left;
38+
if (s.getLeft() instanceof ImVarArrayAccess) {
39+
// Assignment LHS must stay a writable table access, never an ensured r-value wrapper.
40+
left = ExprTranslation.translateArrayAccessRaw((ImVarArrayAccess) s.getLeft(), tr);
41+
} else {
42+
left = s.getLeft().translateToLua(tr);
43+
}
3844
LuaExpr right = s.getRight().translateToLua(tr);
3945
if (s.getRight().attrTyp() instanceof ImTupleType) {
4046
ImTupleType tt = (ImTupleType) s.getRight().attrTyp();

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

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ private void assertDoesNotContainRegex(String output, String regex) {
6565
assertFalse("Pattern must not occur: " + regex, matcher.find());
6666
}
6767

68+
private void assertContainsRegex(String output, String regex) {
69+
Pattern pattern = Pattern.compile(regex);
70+
Matcher matcher = pattern.matcher(output);
71+
assertTrue("Pattern must occur: " + regex, matcher.find());
72+
}
73+
6874
@Test
6975
public void testStdLib() throws IOException {
7076
test().testLua(true).withStdLib().lines(
@@ -214,13 +220,56 @@ public void numericOpsAreGuardedWithEnsure() throws IOException {
214220
" return a < b",
215221
"function divi(int a, int b) returns int",
216222
" return a div b",
223+
"function addi(int a, int b) returns int",
224+
" return a + b",
217225
"init",
218226
" cmp(1, 2)",
219-
" divi(2, 1)"
227+
" divi(2, 1)",
228+
" addi(1, 2)"
220229
);
221230
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_numericOpsAreGuardedWithEnsure.lua"), Charsets.UTF_8);
222-
assertFunctionBodyContains(compiled, "cmp", "realEnsure", true);
231+
assertFunctionBodyContains(compiled, "cmp", "intEnsure", true);
223232
assertFunctionBodyContains(compiled, "divi", "intEnsure", true);
233+
assertTrue(compiled.contains("function addi") && (compiled.contains("realEnsure(a2)") || compiled.contains("intEnsure(a2)")));
234+
}
235+
236+
@Test
237+
public void lazyGenericClosureDispatchWorksInLua() throws IOException {
238+
test().testLua(true).lines(
239+
"package Test",
240+
"native testSuccess()",
241+
"public function lazy<T:>(Lazy<T> l) returns Lazy<T>",
242+
" return l",
243+
"public abstract class Lazy<T:>",
244+
" T val = null",
245+
" var wasRetrieved = false",
246+
" abstract function retrieve() returns T",
247+
" function get() returns T",
248+
" if not wasRetrieved",
249+
" val = retrieve()",
250+
" wasRetrieved = true",
251+
" return val",
252+
"init",
253+
" let l = lazy<int>(() -> 5)",
254+
" if l.get() == 5",
255+
" testSuccess()"
256+
);
257+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_lazyGenericClosureDispatchWorksInLua.lua"), Charsets.UTF_8);
258+
assertTrue(compiled.contains("Lazy_lazy_Test.Lazy_retrieve ="));
259+
assertTrue(compiled.contains("l:Lazy_get()"));
260+
}
261+
262+
@Test
263+
public void stringArrayReadIsEnsured() throws IOException {
264+
test().testLua(true).withStdLib().lines(
265+
"package Test",
266+
"string array playerName",
267+
"init",
268+
" let i = 0",
269+
" SetPlayerName(Player(i), playerName[i])"
270+
);
271+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_stringArrayReadIsEnsured.lua"), Charsets.UTF_8);
272+
assertContainsRegex(compiled, "SetPlayerName\\(Player\\([^\\)]*\\),\\s*stringEnsure\\(");
224273
}
225274

226275
@Test
@@ -563,4 +612,23 @@ public void luaErrorWrapperIgnoresAbortSentinel() throws IOException {
563612
assertTrue(compiled.contains("if err2 == \"__wurst_abort_thread\" then return end"));
564613
}
565614

615+
@Test
616+
public void removesUnusedClassesFromLuaOutput() throws IOException {
617+
test().testLua(true).lines(
618+
"package Test",
619+
"class Keep",
620+
" function ping()",
621+
" skip",
622+
"class Drop",
623+
" function pong()",
624+
" skip",
625+
"init",
626+
" let k = new Keep()",
627+
" k.ping()"
628+
);
629+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_removesUnusedClassesFromLuaOutput.lua"), Charsets.UTF_8);
630+
assertTrue(compiled.contains("Keep"));
631+
assertFalse(compiled.contains("Drop"));
632+
}
633+
566634
}

0 commit comments

Comments
 (0)