mirror of
https://github.com/irmen/prog8.git
synced 2024-09-10 09:54:32 +00:00
optimize dangling else
This commit is contained in:
parent
0aac9350d5
commit
a587482edf
@ -43,9 +43,9 @@ fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget)
|
|||||||
|
|
||||||
fun Program.optimizeStatements(errors: IErrorReporter,
|
fun Program.optimizeStatements(errors: IErrorReporter,
|
||||||
functions: IBuiltinFunctions,
|
functions: IBuiltinFunctions,
|
||||||
compTarget: ICompilationTarget
|
options: CompilationOptions
|
||||||
): Int {
|
): Int {
|
||||||
val optimizer = StatementOptimizer(this, errors, functions, compTarget)
|
val optimizer = StatementOptimizer(this, errors, functions, options)
|
||||||
optimizer.visit(this)
|
optimizer.visit(this)
|
||||||
val optimizationCount = optimizer.applyModifications()
|
val optimizationCount = optimizer.applyModifications()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import kotlin.math.floor
|
|||||||
class StatementOptimizer(private val program: Program,
|
class StatementOptimizer(private val program: Program,
|
||||||
private val errors: IErrorReporter,
|
private val errors: IErrorReporter,
|
||||||
private val functions: IBuiltinFunctions,
|
private val functions: IBuiltinFunctions,
|
||||||
private val compTarget: ICompilationTarget
|
private val options: CompilationOptions
|
||||||
) : AstWalker() {
|
) : AstWalker() {
|
||||||
|
|
||||||
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||||
@ -39,7 +39,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if(string!=null) {
|
if(string!=null) {
|
||||||
val pos = functionCallStatement.position
|
val pos = functionCallStatement.position
|
||||||
if (string.value.length == 1) {
|
if (string.value.length == 1) {
|
||||||
val firstCharEncoded = compTarget.encodeString(string.value, string.encoding)[0]
|
val firstCharEncoded = options.compTarget.encodeString(string.value, string.encoding)[0]
|
||||||
val chrout = FunctionCallStatement(
|
val chrout = FunctionCallStatement(
|
||||||
IdentifierReference(listOf("txt", "chrout"), pos),
|
IdentifierReference(listOf("txt", "chrout"), pos),
|
||||||
mutableListOf(NumericLiteral(DataType.UBYTE, firstCharEncoded.toDouble(), pos)),
|
mutableListOf(NumericLiteral(DataType.UBYTE, firstCharEncoded.toDouble(), pos)),
|
||||||
@ -51,7 +51,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
IAstModification.Remove(stringDecl, stringDecl.parent as IStatementContainer)
|
IAstModification.Remove(stringDecl, stringDecl.parent as IStatementContainer)
|
||||||
)
|
)
|
||||||
} else if (string.value.length == 2) {
|
} else if (string.value.length == 2) {
|
||||||
val firstTwoCharsEncoded = compTarget.encodeString(string.value.take(2), string.encoding)
|
val firstTwoCharsEncoded = options.compTarget.encodeString(string.value.take(2), string.encoding)
|
||||||
val chrout1 = FunctionCallStatement(
|
val chrout1 = FunctionCallStatement(
|
||||||
IdentifierReference(listOf("txt", "chrout"), pos),
|
IdentifierReference(listOf("txt", "chrout"), pos),
|
||||||
mutableListOf(NumericLiteral(DataType.UBYTE, firstTwoCharsEncoded[0].toDouble(), pos)),
|
mutableListOf(NumericLiteral(DataType.UBYTE, firstTwoCharsEncoded[0].toDouble(), pos)),
|
||||||
@ -108,6 +108,16 @@ class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove obvious dangling elses (else after a return)
|
||||||
|
if(ifElse.elsepart.isNotEmpty() && ifElse.truepart.statements.singleOrNull() is Return) {
|
||||||
|
val elsePart = AnonymousScope(ifElse.elsepart.statements, ifElse.elsepart.position)
|
||||||
|
if(options.slowCodegenWarnings)
|
||||||
|
errors.warn("else can be omitted", ifElse.elsepart.position)
|
||||||
|
return listOf(
|
||||||
|
IAstModification.ReplaceNode(ifElse.elsepart, AnonymousScope(mutableListOf(), ifElse.elsepart.position), ifElse),
|
||||||
|
IAstModification.InsertAfter(ifElse, elsePart, parent as IStatementContainer)
|
||||||
|
)
|
||||||
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +151,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
val size = sv.value.length
|
val size = sv.value.length
|
||||||
if(size==1) {
|
if(size==1) {
|
||||||
// loop over string of length 1 -> just assign the single character
|
// loop over string of length 1 -> just assign the single character
|
||||||
val character = compTarget.encodeString(sv.value, sv.encoding)[0]
|
val character = options.compTarget.encodeString(sv.value, sv.encoding)[0]
|
||||||
val byte = NumericLiteral(DataType.UBYTE, character.toDouble(), iterable.position)
|
val byte = NumericLiteral(DataType.UBYTE, character.toDouble(), iterable.position)
|
||||||
val scope = AnonymousScope(mutableListOf(), forLoop.position)
|
val scope = AnonymousScope(mutableListOf(), forLoop.position)
|
||||||
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, AssignmentOrigin.OPTIMIZER, forLoop.position))
|
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, AssignmentOrigin.OPTIMIZER, forLoop.position))
|
||||||
@ -326,7 +336,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if (rightCv == 0.0) {
|
if (rightCv == 0.0) {
|
||||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && compTarget.name!=VMTarget.NAME) {
|
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
|
||||||
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
|
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
|
||||||
val incs = AnonymousScope(mutableListOf(), assignment.position)
|
val incs = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
repeat(rightCv.toInt()) {
|
repeat(rightCv.toInt()) {
|
||||||
@ -340,7 +350,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if (rightCv == 0.0) {
|
if (rightCv == 0.0) {
|
||||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && compTarget.name!=VMTarget.NAME) {
|
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
|
||||||
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
|
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
|
||||||
val decs = AnonymousScope(mutableListOf(), assignment.position)
|
val decs = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
repeat(rightCv.toInt()) {
|
repeat(rightCv.toInt()) {
|
||||||
|
@ -371,7 +371,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
|||||||
// keep optimizing expressions and statements until no more steps remain
|
// keep optimizing expressions and statements until no more steps remain
|
||||||
val optsDone1 = program.simplifyExpressions(errors, compTarget)
|
val optsDone1 = program.simplifyExpressions(errors, compTarget)
|
||||||
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
|
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
|
||||||
val optsDone3 = program.optimizeStatements(errors, functions, compTarget)
|
val optsDone3 = program.optimizeStatements(errors, functions, compilerOptions)
|
||||||
val optsDone4 = program.inlineSubroutines()
|
val optsDone4 = program.inlineSubroutines()
|
||||||
program.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
|
program.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
|
||||||
errors.report()
|
errors.report()
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- optimize a "dangling else"
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,67 +1,41 @@
|
|||||||
%import math
|
|
||||||
%import textio
|
%import textio
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
const ubyte WIDTH=255
|
|
||||||
const ubyte HEIGHT=240
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
sys.gfx_enable(0) ; enable lo res screen
|
txt.print_ub(danglingelse(32))
|
||||||
;; gfx2.screen_mode(4)
|
txt.spc()
|
||||||
repeat {
|
txt.print_ub(danglingelse(99))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(danglingelse(1))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(danglingelse(100))
|
||||||
|
txt.nl()
|
||||||
|
txt.print_ub(danglingelse2(32))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(danglingelse2(99))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(danglingelse2(1))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(danglingelse2(100))
|
||||||
|
txt.nl()
|
||||||
|
}
|
||||||
|
|
||||||
ubyte xx
|
sub danglingelse(ubyte bb) -> ubyte {
|
||||||
ubyte yy
|
if bb==32
|
||||||
|
return 32
|
||||||
|
else if bb==99
|
||||||
|
return 99
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
for yy in 0 to HEIGHT-1 {
|
sub danglingelse2(ubyte bb) -> ubyte {
|
||||||
for xx in 0 to WIDTH-1 {
|
if bb==32
|
||||||
ubyte value = math.direction(WIDTH/2, HEIGHT/2, xx, yy)
|
return 32
|
||||||
;; gfx2.plot(xx,yy,value)
|
if bb==99
|
||||||
sys.gfx_plot(xx, yy, value*10)
|
return 99
|
||||||
}
|
return 0
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
;main {
|
|
||||||
;
|
|
||||||
; sub start() {
|
|
||||||
;
|
|
||||||
; const ubyte HEIGHT = txt.DEFAULT_HEIGHT
|
|
||||||
; const ubyte WIDTH = txt.DEFAULT_WIDTH
|
|
||||||
; const ubyte HALFWIDTH = txt.DEFAULT_WIDTH/2
|
|
||||||
; const ubyte HALFHEIGHT = txt.DEFAULT_HEIGHT/2
|
|
||||||
;
|
|
||||||
; ubyte @zp value
|
|
||||||
; ubyte xx
|
|
||||||
; ubyte yy
|
|
||||||
;; for yy in 0 to HEIGHT-1 {
|
|
||||||
;; for xx in 0 to WIDTH-1 {
|
|
||||||
;; value = math.atan(HALFWIDTH, HALFHEIGHT, xx, yy)
|
|
||||||
;; txt.setchr(xx,yy,value)
|
|
||||||
;; }
|
|
||||||
;; }
|
|
||||||
;;
|
|
||||||
;; byte sx
|
|
||||||
;; byte sy
|
|
||||||
;; for sy in -HEIGHT/2 to HEIGHT/2 {
|
|
||||||
;; for sx in -WIDTH/2 to WIDTH/2 {
|
|
||||||
;; value = math.direction_sc(0, 0, sx, sy)
|
|
||||||
;; txt.setchr(sx+WIDTH/2 as ubyte,sy+HEIGHT/2 as ubyte,value)
|
|
||||||
;; }
|
|
||||||
;; }
|
|
||||||
;
|
|
||||||
; for yy in 0 to HEIGHT-1 {
|
|
||||||
; for xx in 0 to WIDTH-1 {
|
|
||||||
; value = math.direction(HALFWIDTH, HALFHEIGHT, xx, yy)
|
|
||||||
; txt.setchr(xx,yy,value)
|
|
||||||
; }
|
|
||||||
; }
|
|
||||||
;
|
|
||||||
; goto start
|
|
||||||
; }
|
|
||||||
;}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user