Skip to content

Commit f808b69

Browse files
committed
Fix lua name normalization
1 parent 6675bdc commit f808b69

2 files changed

Lines changed: 84 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(name)) {
7879
name = uniqueName(name);
80+
} else if (isFixedEntryPoint(name)) {
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(String name) {
222+
return "main".equals(name) || "config".equals(name);
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: 39 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,42 @@ 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+
"int main = 1",
219+
"int config = 2",
220+
"init",
221+
" if main > 0 and config > 0",
222+
" skip"
223+
);
224+
String compiled = Files.toString(new File("test-output/lua/LuaTranslationTests_mainAndConfigNamesFixed.lua"), Charsets.UTF_8);
225+
assertTrue(compiled.contains("function main("));
226+
assertTrue(compiled.contains("function config("));
227+
assertFalse(compiled.contains("function main2("));
228+
assertFalse(compiled.contains("function config2("));
229+
assertFalse(compiled.contains("local main ="));
230+
assertFalse(compiled.contains("local config ="));
231+
}
232+
194233
@Test
195234
public void intCasting() throws IOException {
196235
// Use local variables to test if it works even when local types are eliminated.
@@ -234,4 +273,3 @@ public void intCasting() throws IOException {
234273
assertFunctionBodyContains(compiled, "testClass", "cObj2 = cInt", false);
235274
}
236275
}
237-

0 commit comments

Comments
 (0)