diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaNatives.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaNatives.java index c3a705f08..59be0bce8 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaNatives.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaNatives.java @@ -125,9 +125,9 @@ private static void addNative(Iterable names, Consumer f) { } public static void get(LuaFunction f) { - nativeCodes.getOrDefault(f.getName(), name -> { + nativeCodes.getOrDefault(f.getName(), ff -> { // generate a runtime exception - f.getBody().add(LuaAst.LuaLiteral("error(\"The native '" + name + "' is not implemented.\")")); + f.getBody().add(LuaAst.LuaLiteral("error(\"The native '" + ff.getName() + "' is not implemented.\")")); }).accept(f); } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java index 706af5aea..0556e7faa 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java @@ -117,6 +117,7 @@ protected String uniqueName(String name) { } public LuaCompilationUnit translate() { + RemoveGarbage.removeGarbage(prog); prog.flatten(imTr); normalizeMethodNames(); @@ -251,6 +252,10 @@ private void cleanStatements(LuaStatements stmts) { } private void translateFunc(ImFunction f) { + if (f.isBj()) { + // do not translate blizzard functions + return; + } LuaFunction lf = luaFunc.getFor(f); if (f.isNative()) { LuaNatives.get(lf); @@ -279,7 +284,7 @@ private void translateFunc(ImFunction f) { translateStatements(lf.getBody(), f.getBody()); } - if (f.isExtern() || f.isNative() ||f.isBj()) { + if (f.isExtern() || f.isNative()) { // only add the function if it is not yet defined: String name = lf.getName(); luaModel.add(LuaAst.LuaIf( @@ -417,6 +422,10 @@ private void collectSuperClasses(LuaTableFields superClasses, ImClass c, Set functions = new HashSet<>(); + private Set methods = new HashSet<>(); + // methods that will be added once the class is used: + private Multimap waitingMethods = HashMultimap.create(); + private Set classes = new HashSet<>(); + private Set vars = new HashSet<>(); + + public void addMethod(ImMethod m) { + methods.add(m); + } + + public void maybeVisitMethod(ImMethod m) { + ImClass c = m.attrClass(); + if (classes.contains(c)) { + visitMethod(m, this); + } else { + waitingMethods.put(c, m); + } + } + + public Set getFunctions() { + return functions; + } + + public Set getMethods() { + return methods; + } + + public Set getClasses() { + return classes; + } + + public Set getVars() { + return vars; + } + + public void addFunction(ImFunction f) { + functions.add(f); + } + + public void addVar(ImVar var) { + vars.add(var); + } + + public void addClass(ImClass c) { + classes.add(c); + Collection imMethods = waitingMethods.get(c); + Iterator it = imMethods.iterator(); + while (it.hasNext()) { + ImMethod m = it.next(); + visitMethod(m, this); + it.remove(); + } + } + } + + public static void removeGarbage(ImProg prog) { + Used used = new Used(); + for (ImFunction f : prog.getFunctions()) { + if (f.getName().equals("main") + || f.getName().equals("config")) { + visitFunction(f, used); + } + } + + prog.getClasses().removeIf(c -> !used.getClasses().contains(c)); + prog.getGlobals().removeIf(g -> !used.getVars().contains(g)); + prog.getFunctions().removeIf(f -> !used.getFunctions().contains(f)); + for (ImClass c : prog.getClasses()) { + c.getFields().removeIf(g -> !used.getVars().contains(g)); + c.getFunctions().removeIf(f -> !used.getFunctions().contains(f)); + c.getMethods().removeIf(m -> !used.getMethods().contains(m)); + for (ImMethod m : c.getMethods()) { + m.getSubMethods().removeIf(sm -> !used.getMethods().contains(sm)); + } + } + + } + + private static void visitFunction(ImFunction f, Used used) { + if (used.getFunctions().contains(f)) { + return; + } + used.addFunction(f); + + visitType(f.getReturnType(), used); + f.accept(new Element.DefaultVisitor() { + @Override + public void visit(ImFunctionCall e) { + super.visit(e); + visitFunction(e.getFunc(), used); + } + + @Override + public void visit(ImVar e) { + super.visit(e); + visitType(e.getType(), used); + } + + @Override + public void visit(ImFuncRef e) { + super.visit(e); + visitFunction(e.getFunc(), used); + } + + @Override + public void visit(ImCast e) { + super.visit(e); + visitType(e.getToType(), used); + } + + @Override + public void visit(ImVarAccess e) { + super.visit(e); + used.addVar(e.getVar()); + } + + @Override + public void visit(ImVarArrayAccess e) { + super.visit(e); + used.addVar(e.getVar()); + } + + @Override + public void visit(ImAlloc e) { + super.visit(e); + visitClass(e.getClazz().getClassDef(), used); + } + + @Override + public void visit(ImDealloc e) { + super.visit(e); + visitClass(e.getClazz().getClassDef(), used); + } + + @Override + public void visit(ImInstanceof e) { + super.visit(e); + visitClass(e.getClazz().getClassDef(), used); + } + + @Override + public void visit(ImTypeIdOfObj e) { + super.visit(e); + visitClass(e.getClazz().getClassDef(), used); + } + + @Override + public void visit(ImTypeIdOfClass e) { + super.visit(e); + visitClass(e.getClazz().getClassDef(), used); + } + + @Override + public void visit(ImMethodCall e) { + super.visit(e); + visitMethod(e.getMethod(), used); + } + + @Override + public void visit(ImMemberAccess e) { + super.visit(e); + used.addVar(e.getVar()); + } + }); + } + + private static void visitMethod(ImMethod m, Used used) { + if (used.getMethods().contains(m)) { + return; + } + used.addMethod(m); + visitClass(m.getMethodClass().getClassDef(), used); + visitFunction(m.getImplementation(), used); + for (ImMethod subMethod : m.getSubMethods()) { + used.maybeVisitMethod(subMethod); + } + } + + private static void visitClass(ImClass c, Used used) { + if (used.getClasses().contains(c)) { + return; + } + used.addClass(c); + for (ImClassType superClass : c.getSuperClasses()) { + visitClass(superClass.getClassDef(), used); + } + } + + private static void visitType(ImType t, Used used) { + t.match(new ImType.MatcherVoid() { + + @Override + public void case_ImTupleType(ImTupleType tt) { + for (ImType type : tt.getTypes()) { + visitType(type, used); + } + } + + @Override + public void case_ImTypeVarRef(ImTypeVarRef tt) { + + } + + @Override + public void case_ImVoid(ImVoid tt) { + + } + + @Override + public void case_ImSimpleType(ImSimpleType tt) { + + } + + @Override + public void case_ImArrayTypeMulti(ImArrayTypeMulti tt) { + visitType(tt.getEntryType(), used); + } + + @Override + public void case_ImClassType(ImClassType tt) { + visitClass(tt.getClassDef(), used); + for (ImTypeArgument ta : tt.getTypeArguments()) { + visitType(ta.getType(), used); + } + } + + @Override + public void case_ImArrayType(ImArrayType tt) { + visitType(tt.getEntryType(), used); + } + }); + + } +}