mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
use var initializer assignments in a clearer way
This commit is contained in:
parent
de3b2fb95b
commit
056ec986c2
@ -220,11 +220,7 @@ class AsmGen(private val program: Program,
|
||||
if(options.dontReinitGlobals) {
|
||||
block.statements.asSequence().filterIsInstance<VarDecl>().forEach {
|
||||
it.zeropage = ZeropageWish.NOT_IN_ZEROPAGE
|
||||
val init = it.nextSibling() as? Assignment
|
||||
if(init?.target?.identifier?.targetVarDecl(program) === it) {
|
||||
// put the init value back into the vardecl
|
||||
it.value = init.value
|
||||
}
|
||||
it.findInitializer(program)?.let { initializer -> it.value = initializer.value } // put the init value back into the vardecl
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,4 +85,16 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter) : AstWal
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
val nextAssignment = decl.nextSibling() as? Assignment
|
||||
if(nextAssignment!=null && nextAssignment.origin!=AssignmentOrigin.VARINIT) {
|
||||
// check if it's a proper initializer assignment for the variable
|
||||
if(decl.value==null && nextAssignment.target.identifier?.targetVarDecl(program)===decl) {
|
||||
if(!nextAssignment.value.referencesIdentifier(nextAssignment.target.identifier!!.nameInSource))
|
||||
nextAssignment.origin = AssignmentOrigin.VARINIT
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
@ -58,16 +58,9 @@ internal class StatementReorderer(val program: Program,
|
||||
// no need to zero out the special internal returnvalue intermediates.
|
||||
return noModifications
|
||||
}
|
||||
val nextStmt = decl.nextSibling()
|
||||
val nextAssign = nextStmt as? Assignment
|
||||
if(nextAssign!=null && !nextAssign.isAugmentable) {
|
||||
val target = nextAssign.target.identifier?.targetStatement(program)
|
||||
if(target === decl) {
|
||||
// an initializer assignment for a vardecl is already here
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
val nextFor = nextStmt as? ForLoop
|
||||
if(decl.findInitializer(program)!=null)
|
||||
return noModifications // an initializer assignment for a vardecl is already here
|
||||
val nextFor = decl.nextSibling() as? ForLoop
|
||||
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
|
||||
if (!hasNextForWithThisLoopvar) {
|
||||
// Add assignment to initialize with zero
|
||||
|
@ -10,7 +10,6 @@ import prog8.ast.base.DataType
|
||||
import prog8.ast.base.VarDeclType
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.codegen.target.Cx16Target
|
||||
import prog8tests.helpers.assertSuccess
|
||||
import prog8tests.helpers.compileText
|
||||
@ -76,7 +75,7 @@ class TestCompilerOnCharLit: FunSpec({
|
||||
withClue("initializer value should have been moved to separate assignment"){
|
||||
decl.value shouldBe null
|
||||
}
|
||||
val assignInitialValue = decl.nextSibling() as Assignment
|
||||
val assignInitialValue = decl.findInitializer(program)!!
|
||||
assignInitialValue.target.identifier!!.nameInSource shouldBe listOf("ch")
|
||||
withClue("char literal should have been replaced by ubyte literal") {
|
||||
assignInitialValue.value shouldBe instanceOf<NumericLiteralValue>()
|
||||
|
@ -604,24 +604,26 @@ class TestOptimization: FunSpec({
|
||||
uword @shared zz
|
||||
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
||||
ubyte @shared xx
|
||||
xx = 6+sin8u(xx) ; NOT ok to remove initializer
|
||||
xx = 6+sin8u(xx) ; is not an initializer because it references xx
|
||||
}
|
||||
}
|
||||
"""
|
||||
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
|
||||
printProgram(result.program)
|
||||
/* expected result:
|
||||
uword yy
|
||||
yy = 20
|
||||
uword zz
|
||||
zz = 60
|
||||
ubyte xx
|
||||
xx = 0
|
||||
xx = sin8u(xx)
|
||||
xx += 6
|
||||
*/
|
||||
val stmts = result.program.entrypoint.statements
|
||||
stmts.size shouldBe 7
|
||||
stmts.size shouldBe 8
|
||||
stmts.filterIsInstance<VarDecl>().size shouldBe 3
|
||||
stmts.filterIsInstance<Assignment>().size shouldBe 4
|
||||
stmts.filterIsInstance<Assignment>().size shouldBe 5
|
||||
}
|
||||
|
||||
test("only substitue assignments with 0 after a =0 initializer if it is the same variable") {
|
||||
|
@ -272,6 +272,12 @@ class VarDecl(val type: VarDeclType,
|
||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
return copy
|
||||
}
|
||||
|
||||
fun findInitializer(program: Program): Assignment? =
|
||||
(parent as IStatementContainer).statements
|
||||
.asSequence()
|
||||
.filterIsInstance<Assignment>()
|
||||
.singleOrNull { it.origin==AssignmentOrigin.VARINIT && it.target.identifier?.targetVarDecl(program) === this }
|
||||
}
|
||||
|
||||
class ArrayIndex(var indexExpr: Expression,
|
||||
@ -399,6 +405,12 @@ class Assignment(var target: AssignTarget, var value: Expression, var origin: As
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun initializerFor(program: Program) =
|
||||
if(origin==AssignmentOrigin.VARINIT)
|
||||
target.identifier!!.targetVarDecl(program)
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
data class AssignTarget(var identifier: IdentifierReference?,
|
||||
|
@ -3,7 +3,6 @@ TODO
|
||||
|
||||
For next compiler release (7.7)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- use the assignment origin? in codegen? (origin VARINIT)
|
||||
- optimize codegen of pipe operator to avoid needless assigns to temp var
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user