mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 04:30:03 +00:00
fix improperly changed behavior about =0 initializer
This commit is contained in:
parent
dafa0d9138
commit
4c82af36e6
@ -56,15 +56,12 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
val nextStmt = decl.nextSibling()
|
val nextStmt = decl.nextSibling()
|
||||||
val nextAssign = nextStmt as? Assignment
|
|
||||||
val nextFor = nextStmt as? ForLoop
|
val nextFor = nextStmt as? ForLoop
|
||||||
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
|
val hasNextForWithThisLoopvar = nextFor?.loopVar?.nameInSource==listOf(decl.name)
|
||||||
val hasNextAssignmentThatAlsoInitializes = nextAssign!=null
|
if (!hasNextForWithThisLoopvar) {
|
||||||
&& nextAssign.target isSameAs IdentifierReference(listOf(decl.name), Position.DUMMY)
|
|
||||||
&& !nextAssign.isAugmentable
|
|
||||||
if (!hasNextAssignmentThatAlsoInitializes && !hasNextForWithThisLoopvar) {
|
|
||||||
// Add assignment to initialize with zero
|
// Add assignment to initialize with zero
|
||||||
// Note: for block-level vars, this will introduce assignments in the block scope. These have to be dealt with correctly later.
|
// Note: for block-level vars, this will introduce assignments in the block scope. These have to be dealt with correctly later.
|
||||||
|
// TODO optimize this a bit so that we don't add this statement if the next one would already be an assignment to the same variable
|
||||||
val identifier = IdentifierReference(listOf(decl.name), decl.position)
|
val identifier = IdentifierReference(listOf(decl.name), decl.position)
|
||||||
val assignzero = Assignment(AssignTarget(identifier, null, null, decl.position), decl.zeroElementValue(), decl.position)
|
val assignzero = Assignment(AssignTarget(identifier, null, null, decl.position), decl.zeroElementValue(), decl.position)
|
||||||
return listOf(IAstModification.InsertAfter(
|
return listOf(IAstModification.InsertAfter(
|
||||||
|
@ -97,8 +97,20 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter)
|
|||||||
|
|
||||||
val nextAssign = assignment.nextSibling() as? Assignment
|
val nextAssign = assignment.nextSibling() as? Assignment
|
||||||
if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) {
|
if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) {
|
||||||
|
// TODO hmm, if both assignments assign to the same thing, can't we just remove the first altogether???
|
||||||
|
|
||||||
if(nextAssign.value isSameAs assignment.value)
|
if(nextAssign.value isSameAs assignment.value)
|
||||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
|
|
||||||
|
if((assignment.value as? NumericLiteralValue)?.number==0.0 && nextAssign.isAugmentable) {
|
||||||
|
val value = nextAssign.value as BinaryExpression
|
||||||
|
require(value.left isSameAs assignment.target)
|
||||||
|
val assign = Assignment(assignment.target, value.right, nextAssign.position)
|
||||||
|
return listOf(
|
||||||
|
IAstModification.Remove(assignment, parent as IStatementContainer),
|
||||||
|
IAstModification.ReplaceNode(nextAssign, assign, parent)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
|
@ -250,22 +250,21 @@ class TestOptimization: FunSpec({
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte ub
|
ubyte ub
|
||||||
float ff
|
float ff = 1.0
|
||||||
ff += (ub as float) ; operator doesn't matter
|
ff += (ub as float) ; operator doesn't matter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
val result1 = compileText(C64Target, optimize=false, src, writeAssembly = false).assertSuccess()
|
val result = compileText(C64Target, optimize=false, src, writeAssembly = false).assertSuccess()
|
||||||
|
val assignFF = result.program.entrypoint.statements.last() as Assignment
|
||||||
val assignYY = result1.program.entrypoint.statements.last() as Assignment
|
assignFF.isAugmentable shouldBe true
|
||||||
assignYY.isAugmentable shouldBe true
|
assignFF.target.identifier!!.nameInSource shouldBe listOf("ff")
|
||||||
assignYY.target.identifier!!.nameInSource shouldBe listOf("ff")
|
val value = assignFF.value as BinaryExpression
|
||||||
val value = assignYY.value as BinaryExpression
|
|
||||||
value.operator shouldBe "+"
|
value.operator shouldBe "+"
|
||||||
value.left shouldBe IdentifierReference(listOf("ff"), Position.DUMMY)
|
value.left shouldBe IdentifierReference(listOf("ff"), Position.DUMMY)
|
||||||
value.right shouldBe instanceOf<TypecastExpression>()
|
value.right shouldBe instanceOf<TypecastExpression>()
|
||||||
|
|
||||||
val asm = generateAssembly(result1.program)
|
val asm = generateAssembly(result.program)
|
||||||
asm.valid shouldBe true
|
asm.valid shouldBe true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,10 +325,12 @@ class TestOptimization: FunSpec({
|
|||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte z1
|
ubyte @shared z1
|
||||||
z1 = 10
|
z1 = 10
|
||||||
ubyte z2
|
ubyte @shared z2
|
||||||
z2 = z1+z2+5
|
z2 = z1+z2+5
|
||||||
|
ubyte @shared z3
|
||||||
|
z3 = z1+z3-5
|
||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
|
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
|
||||||
@ -337,27 +338,34 @@ class TestOptimization: FunSpec({
|
|||||||
ubyte z1
|
ubyte z1
|
||||||
z1 = 10
|
z1 = 10
|
||||||
ubyte z2
|
ubyte z2
|
||||||
z2 = 0
|
z2 = z1
|
||||||
z2 += z1 ; TODO actually add optimization to make this even better: no =0, and this should become z2 = z1
|
|
||||||
z2 += 5
|
z2 += 5
|
||||||
|
ubyte z3
|
||||||
|
z3 = z1
|
||||||
|
z3 -= 5
|
||||||
*/
|
*/
|
||||||
val statements = result.program.entrypoint.statements
|
val statements = result.program.entrypoint.statements
|
||||||
statements.size shouldBe 6 // TODO 5
|
statements.size shouldBe 8
|
||||||
val z1decl = statements[0] as VarDecl
|
val z1decl = statements[0] as VarDecl
|
||||||
val z1init = statements[1] as Assignment
|
val z1init = statements[1] as Assignment
|
||||||
val z2decl = statements[2] as VarDecl
|
val z2decl = statements[2] as VarDecl
|
||||||
val z2init = statements[3] as Assignment
|
val z2init = statements[3] as Assignment
|
||||||
val z2plus1 = statements[4] as Assignment
|
val z2plus = statements[4] as Assignment
|
||||||
val z2plus2= statements[5] as Assignment
|
val z3decl = statements[5] as VarDecl
|
||||||
|
val z3init = statements[6] as Assignment
|
||||||
|
val z3plus = statements[7] as Assignment
|
||||||
|
|
||||||
z1decl.name shouldBe "z1"
|
z1decl.name shouldBe "z1"
|
||||||
z1init.value shouldBe NumericLiteralValue(DataType.UBYTE, 10.0, Position.DUMMY)
|
z1init.value shouldBe NumericLiteralValue(DataType.UBYTE, 10.0, Position.DUMMY)
|
||||||
z2decl.name shouldBe "z2"
|
z2decl.name shouldBe "z2"
|
||||||
z2init.value shouldBe NumericLiteralValue(DataType.UBYTE, 0.0, Position.DUMMY)
|
z2init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
|
||||||
z2plus1.isAugmentable shouldBe true
|
z2plus.isAugmentable shouldBe true
|
||||||
(z2plus1.value as BinaryExpression).operator shouldBe "+"
|
(z2plus.value as BinaryExpression).operator shouldBe "+"
|
||||||
(z2plus1.value as BinaryExpression).right shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
|
(z2plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
|
||||||
(z2plus2.value as BinaryExpression).operator shouldBe "+"
|
z3decl.name shouldBe "z3"
|
||||||
(z2plus2.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
|
z3init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
|
||||||
|
z3plus.isAugmentable shouldBe true
|
||||||
|
(z3plus.value as BinaryExpression).operator shouldBe "-"
|
||||||
|
(z3plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -9,6 +9,7 @@ import io.kotest.matchers.types.instanceOf
|
|||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
import prog8.compiler.printAst
|
||||||
import prog8.compiler.target.C64Target
|
import prog8.compiler.target.C64Target
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
import prog8tests.helpers.assertFailure
|
import prog8tests.helpers.assertFailure
|
||||||
@ -191,10 +192,10 @@ class TestSubroutines: FunSpec({
|
|||||||
val text="""
|
val text="""
|
||||||
main {
|
main {
|
||||||
sub thing(uword rr) {
|
sub thing(uword rr) {
|
||||||
ubyte xx = rr[1] ; should still work as var initializer that will be rewritten
|
ubyte @shared xx = rr[1] ; should still work as var initializer that will be rewritten
|
||||||
ubyte yy
|
ubyte @shared yy
|
||||||
yy = rr[2]
|
yy = rr[2]
|
||||||
uword other
|
uword @shared other
|
||||||
ubyte zz = other[3]
|
ubyte zz = other[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,14 +211,14 @@ class TestSubroutines: FunSpec({
|
|||||||
val block = module.statements.single() as Block
|
val block = module.statements.single() as Block
|
||||||
val thing = block.statements.filterIsInstance<Subroutine>().single {it.name=="thing"}
|
val thing = block.statements.filterIsInstance<Subroutine>().single {it.name=="thing"}
|
||||||
block.name shouldBe "main"
|
block.name shouldBe "main"
|
||||||
thing.statements.size shouldBe 10 // rr, xx, xx assign, yy, yy assign, other, other assign 0, zz, zz assign, return
|
thing.statements.size shouldBe 11 // rr paramdecl, xx, xx assign, yy decl, yy init 0, yy assign, other, other assign 0, zz, zz assign, return
|
||||||
val xx = thing.statements[1] as VarDecl
|
val xx = thing.statements[1] as VarDecl
|
||||||
withClue("vardecl init values must have been moved to separate assignments") {
|
withClue("vardecl init values must have been moved to separate assignments") {
|
||||||
xx.value shouldBe null
|
xx.value shouldBe null
|
||||||
}
|
}
|
||||||
val assignXX = thing.statements[2] as Assignment
|
val assignXX = thing.statements[2] as Assignment
|
||||||
val assignYY = thing.statements[4] as Assignment
|
val assignYY = thing.statements[5] as Assignment
|
||||||
val assignZZ = thing.statements[8] as Assignment
|
val assignZZ = thing.statements[9] as Assignment
|
||||||
assignXX.target.identifier!!.nameInSource shouldBe listOf("xx")
|
assignXX.target.identifier!!.nameInSource shouldBe listOf("xx")
|
||||||
assignYY.target.identifier!!.nameInSource shouldBe listOf("yy")
|
assignYY.target.identifier!!.nameInSource shouldBe listOf("yy")
|
||||||
assignZZ.target.identifier!!.nameInSource shouldBe listOf("zz")
|
assignZZ.target.identifier!!.nameInSource shouldBe listOf("zz")
|
||||||
|
@ -5,6 +5,9 @@ For next compiler release (7.4)
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
BUG: Fix C-64sound issue in petaxian (regression since 7.3, sound on c64 build works fine on older versions)
|
BUG: Fix C-64sound issue in petaxian (regression since 7.3, sound on c64 build works fine on older versions)
|
||||||
|
|
||||||
|
optimize TODO in "Add assignment to initialize with zero" in StatementReorderer
|
||||||
|
optimize TODO in after(assignment) in VariousCleanups
|
||||||
|
|
||||||
|
|
||||||
Blocked by an official Commander-x16 v39 release
|
Blocked by an official Commander-x16 v39 release
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Loading…
x
Reference in New Issue
Block a user