use new api for ast mods in unused code remover

This commit is contained in:
Irmen de Jong 2020-05-15 00:16:53 +02:00
parent 1978a9815a
commit edee70cf31
3 changed files with 12 additions and 28 deletions

View File

@ -1 +1 @@
2.0
2.1-SNAPSHOT

View File

@ -174,6 +174,7 @@ private fun optimizeAst(programAst: Program, errors: ErrorReporter) {
val remover = UnusedCodeRemover()
remover.visit(programAst)
remover.applyModifications()
}
private fun postprocessAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) {

View File

@ -1,55 +1,38 @@
package prog8.optimizer
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification
import prog8.ast.statements.Block
import prog8.ast.statements.Subroutine
internal class UnusedCodeRemover: IAstModifyingVisitor {
internal class UnusedCodeRemover: AstWalker() {
override fun visit(program: Program) {
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
val callgraph = CallGraph(program)
val removals = mutableListOf<IAstModification>()
// remove all subroutines that aren't called, or are empty
val removeSubroutines = mutableSetOf<Subroutine>()
val entrypoint = program.entrypoint()
program.modules.forEach {
callgraph.forAllSubroutines(it) { sub ->
if (sub !== entrypoint && !sub.keepAlways && (sub.calledBy.isEmpty() || (sub.containsNoCodeNorVars() && !sub.isAsmSubroutine)))
removeSubroutines.add(sub)
removals.add(IAstModification.Remove(sub, sub.definingScope() as Node))
}
}
if (removeSubroutines.isNotEmpty()) {
removeSubroutines.forEach {
it.definingScope().remove(it)
}
}
val removeBlocks = mutableSetOf<Block>()
program.modules.flatMap { it.statements }.filterIsInstance<Block>().forEach { block ->
if (block.containsNoCodeNorVars() && "force_output" !in block.options())
removeBlocks.add(block)
}
if (removeBlocks.isNotEmpty()) {
removeBlocks.forEach { it.definingScope().remove(it) }
removals.add(IAstModification.Remove(block, block.definingScope() as Node))
}
// remove modules that are not imported, or are empty (unless it's a library modules)
val removeModules = mutableSetOf<Module>()
program.modules.forEach {
if (!it.isLibraryModule && (it.importedBy.isEmpty() || it.containsNoCodeNorVars()))
removeModules.add(it)
removals.add(IAstModification.Remove(it, it.parent)) // TODO does removing modules work like this?
}
if (removeModules.isNotEmpty()) {
program.modules.removeAll(removeModules)
}
super.visit(program)
return removals
}
}