mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
add optimization: replace simple for loops by repeat loop
This commit is contained in:
parent
af1b07ad44
commit
1152191f48
@ -166,6 +166,16 @@ class StatementOptimizer(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
val iterationCount = forLoop.constIterationCount(program)
|
||||
if(iterationCount!=null) {
|
||||
val loopName = forLoop.loopVar.nameInSource
|
||||
if(!forLoop.iterable.referencesIdentifier(loopName) && !forLoop.body.referencesIdentifier(loopName)) {
|
||||
errors.warn("for loop can be replaced with repeat loop, possibly also remove the loop variable", forLoop.position)
|
||||
val repeat = RepeatLoop(NumericLiteral.optimalNumeric(iterationCount, forLoop.position), forLoop.body, forLoop.position)
|
||||
return listOf(IAstModification.ReplaceNode(forLoop, repeat, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -125,8 +125,8 @@ class UnusedCodeRemover(private val program: Program,
|
||||
if(usages.size==1) {
|
||||
val singleUse = usages[0].parent
|
||||
if(singleUse is AssignTarget) {
|
||||
val assignment = singleUse.parent as Assignment
|
||||
if(assignment.origin==AssignmentOrigin.VARINIT) {
|
||||
val assignment = singleUse.parent as? Assignment
|
||||
if(assignment!=null && assignment.origin==AssignmentOrigin.VARINIT) {
|
||||
if(assignment.value.isSimple) {
|
||||
// remove the vardecl
|
||||
if(!decl.definingModule.isLibrary)
|
||||
|
@ -863,6 +863,26 @@ class ForLoop(var loopVar: IdentifierReference,
|
||||
body.referencesIdentifier(nameInSource)
|
||||
|
||||
fun loopVarDt(program: Program) = loopVar.inferType(program)
|
||||
|
||||
fun constIterationCount(program: Program): Int? {
|
||||
return when (val iter = iterable) {
|
||||
is IdentifierReference -> {
|
||||
val target = iter.targetVarDecl(program)!!
|
||||
if (target.isArray)
|
||||
target.arraysize!!.constIndex()
|
||||
else if (target.value is StringLiteral)
|
||||
(target.value as StringLiteral).value.length
|
||||
else if (target.value is ArrayLiteral)
|
||||
(target.value as ArrayLiteral).value.size
|
||||
else null
|
||||
}
|
||||
is ArrayLiteral -> iter.value.size
|
||||
is RangeExpression -> iter.size()
|
||||
is StringLiteral -> iter.value.length
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WhileLoop(var condition: Expression,
|
||||
|
@ -3,9 +3,6 @@ TODO
|
||||
|
||||
For next minor release
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
- when a loopvariable of a forloop is *only* referenced in the for loop as loopvariable, and the number of iterations is known, replace the loop by a repeatloop (and remove the vardecl)
|
||||
but we have no efficient way right now to see if the body references a variable. (what about ReferencesIdentifier?)
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user