Skip to content

Commit ef48f98

Browse files
authored
Fix lua name normalization (#1139)
1 parent 6675bdc commit ef48f98

2 files changed

Lines changed: 88 additions & 2 deletions

File tree

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class LuaTranslator {
2727
private final Set<String> usedNames = new HashSet<>(Arrays.asList(
2828
// reserved function names
2929
"print", "tostring", "error",
30+
"main", "config",
3031
// keywords:
3132
"and",
3233
"break",
@@ -74,8 +75,10 @@ public LuaVariable initFor(ImVar a) {
7475
@Override
7576
public LuaFunction initFor(ImFunction a) {
7677
String name = a.getName();
77-
if (!a.isExtern() && !a.isBj() && !a.isNative()) {
78+
if (!a.isExtern() && !a.isBj() && !a.isNative() && !isFixedEntryPoint(a)) {
7879
name = uniqueName(name);
80+
} else if (isFixedEntryPoint(a)) {
81+
usedNames.add(name);
7982
}
8083

8184
LuaFunction lf = LuaAst.LuaFunction(name, LuaAst.LuaParams(), LuaAst.LuaStatements());
@@ -178,6 +181,7 @@ public LuaCompilationUnit translate() {
178181

179182

180183
normalizeMethodNames();
184+
normalizeFieldNames();
181185

182186
// NormalizeNames.normalizeNames(prog);
183187

@@ -214,6 +218,10 @@ public LuaCompilationUnit translate() {
214218
return luaModel;
215219
}
216220

221+
private boolean isFixedEntryPoint(ImFunction function) {
222+
return function == imTr.getMainFunc() || function == imTr.getConfFunc();
223+
}
224+
217225
private void collectPredefinedNames() {
218226
for (ImFunction function : prog.getFunctions()) {
219227
if (function.isBj() || function.isExtern() || function.isNative()) {
@@ -258,6 +266,42 @@ private void normalizeMethodNames() {
258266
}
259267
}
260268

269+
private void normalizeFieldNames() {
270+
for (ImClass c : prog.getClasses()) {
271+
Set<String> methodNames = new HashSet<>();
272+
collectMethodNames(c, methodNames, new HashSet<>());
273+
if (methodNames.isEmpty()) {
274+
continue;
275+
}
276+
Set<String> reserved = new HashSet<>(methodNames);
277+
for (ImVar field : c.getFields()) {
278+
if (reserved.contains(field.getName())) {
279+
String base = field.getName() + "_field";
280+
String candidate = base;
281+
int i = 1;
282+
while (reserved.contains(candidate)) {
283+
candidate = base + i++;
284+
}
285+
field.setName(candidate);
286+
}
287+
reserved.add(field.getName());
288+
}
289+
}
290+
}
291+
292+
private void collectMethodNames(ImClass c, Set<String> methodNames, Set<ImClass> visited) {
293+
if (visited.contains(c)) {
294+
return;
295+
}
296+
visited.add(c);
297+
for (ImMethod method : c.getMethods()) {
298+
methodNames.add(method.getName());
299+
}
300+
for (ImClassType sc : c.getSuperClasses()) {
301+
collectMethodNames(sc.getClassDef(), methodNames, visited);
302+
}
303+
}
304+
261305
private void createStringConcatFunction() {
262306
String[] code = {
263307
"if x then",

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ private void assertFunctionCall(String output, String functionName, String argum
4343
private void assertFunctionBodyContains(String output, String functionName, String search, boolean mustContain) {
4444
Pattern pattern = Pattern.compile("function\\s*" + functionName + "\\s*\\(.*\\).*\\n" + "((?:\\n|.)*?)end");
4545
Matcher matcher = pattern.matcher(output);
46+
boolean found = false;
4647
while (matcher.find()) {
48+
found = true;
4749
String body = matcher.group(1);
4850
if(!body.contains(search) && mustContain) {
4951
fail("Function " + functionName + " must contain " + search + ".");
@@ -52,6 +54,7 @@ private void assertFunctionBodyContains(String output, String functionName, Stri
5254
fail("Function " + functionName + " must not contain " + search + ".");
5355
}
5456
}
57+
assertTrue("Function " + functionName + " was not found.", found);
5558
}
5659

5760
@Test
@@ -191,6 +194,46 @@ public void stringConcatenation() throws IOException {
191194
assertFunctionBodyContains(compiled, "test", "stringConcat", true);
192195
}
193196

197+
@Test
198+
public void methodFieldNameCollision() throws IOException {
199+
test().testLua(true).lines(
200+
"package Test",
201+
"class Foo",
202+
" int size = 3",
203+
" function size() returns int",
204+
" return size",
205+
"init",
206+
" let f = new Foo()",
207+
" f.size()"
208+
);
209+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_methodFieldNameCollision.lua"), Charsets.UTF_8);
210+
assertFunctionBodyContains(compiled, "Foo_Foo_size", "Foo_size_field", true);
211+
assertFunctionBodyContains(compiled, "Foo_Foo_size", "return this.Foo_size\n", false);
212+
}
213+
214+
@Test
215+
public void mainAndConfigNamesFixed() throws IOException {
216+
test().testLua(true).lines(
217+
"package Test",
218+
"native takesInt(int i)",
219+
"function helper()",
220+
" let main = 1",
221+
" let config = 2",
222+
" takesInt(main)",
223+
" takesInt(config)",
224+
"init",
225+
" helper()"
226+
);
227+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_mainAndConfigNamesFixed.lua"), Charsets.UTF_8);
228+
assertFunctionBodyContains(compiled, "helper", "local main1", true);
229+
assertFunctionBodyContains(compiled, "helper", "local config1", true);
230+
assertTrue(compiled.contains("function main("));
231+
assertTrue(compiled.contains("function config("));
232+
assertFalse(compiled.contains("function main2("));
233+
assertFalse(compiled.contains("function config2("));
234+
}
235+
236+
194237
@Test
195238
public void intCasting() throws IOException {
196239
// Use local variables to test if it works even when local types are eliminated.
@@ -234,4 +277,3 @@ public void intCasting() throws IOException {
234277
assertFunctionBodyContains(compiled, "testClass", "cObj2 = cInt", false);
235278
}
236279
}
237-

0 commit comments

Comments
 (0)