mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
slight expression rewrite in case of certain in-place assignments, to try to get the in-place variable operand to the leftmost position
This commit is contained in:
parent
7ac6c8f2d1
commit
fbe3ce008b
@ -289,6 +289,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||||||
override fun visit(assignment: Assignment) {
|
override fun visit(assignment: Assignment) {
|
||||||
val binExpr = assignment.value as? BinaryExpression
|
val binExpr = assignment.value as? BinaryExpression
|
||||||
if(binExpr!=null && binExpr.left isSameAs assignment.target) {
|
if(binExpr!=null && binExpr.left isSameAs assignment.target) {
|
||||||
|
// we only support the inplace assignments of the form A = A <operator> <value>
|
||||||
assignment.target.accept(this)
|
assignment.target.accept(this)
|
||||||
output(" ${binExpr.operator}= ")
|
output(" ${binExpr.operator}= ")
|
||||||
binExpr.right.accept(this)
|
binExpr.right.accept(this)
|
||||||
|
@ -14,8 +14,8 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
// - in every scope, most directives and vardecls are moved to the top.
|
// - in every scope, most directives and vardecls are moved to the top.
|
||||||
// - the 'start' subroutine is moved to the top.
|
// - the 'start' subroutine is moved to the top.
|
||||||
// - (syntax desugaring) a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement.
|
// - (syntax desugaring) a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement.
|
||||||
// - (syntax desugaring) augmented assignment is turned into regular assignment.
|
|
||||||
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
||||||
|
// - in-place assignments are reordered a bit so that they are mostly of the form A = A <operator> <rest>
|
||||||
// - sorts the choices in when statement.
|
// - sorts the choices in when statement.
|
||||||
// - insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
// - insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
||||||
|
|
||||||
@ -118,6 +118,55 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
|
// rewrite in-place assignment expressions a bit so that the assignment target usually is the leftmost operand
|
||||||
|
val binExpr = assignment.value as? BinaryExpression
|
||||||
|
if(binExpr!=null) {
|
||||||
|
if(binExpr.left isSameAs assignment.target) {
|
||||||
|
// A = A <operator> 5, unchanged
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
|
if(binExpr.operator in associativeOperators) {
|
||||||
|
if (binExpr.right isSameAs assignment.target) {
|
||||||
|
// A = v <associative-operator> A ==> A = A <associative-operator> v
|
||||||
|
return listOf(IAstModification.SwapOperands(binExpr))
|
||||||
|
}
|
||||||
|
|
||||||
|
val leftBinExpr = binExpr.left as? BinaryExpression
|
||||||
|
if(leftBinExpr?.operator == binExpr.operator) {
|
||||||
|
return if(leftBinExpr.left isSameAs assignment.target) {
|
||||||
|
// A = (A <associative-operator> x) <same-operator> y ==> A = A <associative-operator> (x <same-operator> y)
|
||||||
|
val newRight = BinaryExpression(leftBinExpr.right, binExpr.operator, binExpr.right, binExpr.position)
|
||||||
|
val newValue = BinaryExpression(leftBinExpr.left, binExpr.operator, newRight, binExpr.position)
|
||||||
|
listOf(IAstModification.ReplaceNode(binExpr, newValue, assignment))
|
||||||
|
} else {
|
||||||
|
// A = (x <associative-operator> A) <same-operator> y ==> A = A <associative-operator> (x <same-operator> y)
|
||||||
|
val newRight = BinaryExpression(leftBinExpr.left, binExpr.operator, binExpr.right, binExpr.position)
|
||||||
|
val newValue = BinaryExpression(leftBinExpr.right, binExpr.operator, newRight, binExpr.position)
|
||||||
|
listOf(IAstModification.ReplaceNode(binExpr, newValue, assignment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val rightBinExpr = binExpr.right as? BinaryExpression
|
||||||
|
if(rightBinExpr?.operator == binExpr.operator) {
|
||||||
|
return if(rightBinExpr.left isSameAs assignment.target) {
|
||||||
|
// A = x <associative-operator> (A <same-operator> y) ==> A = A <associative-operator> (x <same-operator> y)
|
||||||
|
val newRight = BinaryExpression(binExpr.left, binExpr.operator, rightBinExpr.right, binExpr.position)
|
||||||
|
val newValue = BinaryExpression(rightBinExpr.left, binExpr.operator, newRight, binExpr.position)
|
||||||
|
listOf(IAstModification.ReplaceNode(binExpr, newValue, assignment))
|
||||||
|
} else {
|
||||||
|
// A = x <associative-operator> (y <same-operator> A) ==> A = A <associative-operator> (x <same-operator> y)
|
||||||
|
val newRight = BinaryExpression(binExpr.left, binExpr.operator, rightBinExpr.left, binExpr.position)
|
||||||
|
val newValue = BinaryExpression(rightBinExpr.right, binExpr.operator, newRight, binExpr.position)
|
||||||
|
listOf(IAstModification.ReplaceNode(binExpr, newValue, assignment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
private fun flattenStructAssignmentFromStructLiteral(structAssignment: Assignment, program: Program): List<Assignment> {
|
private fun flattenStructAssignmentFromStructLiteral(structAssignment: Assignment, program: Program): List<Assignment> {
|
||||||
val identifier = structAssignment.target.identifier!!
|
val identifier = structAssignment.target.identifier!!
|
||||||
val identifierName = identifier.nameInSource.single()
|
val identifierName = identifier.nameInSource.single()
|
||||||
|
@ -348,6 +348,35 @@ open class Assignment(var target: AssignTarget, var value: Expression, override
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return("Assignment(target: $target, value: $value, pos=$position)")
|
return("Assignment(target: $target, value: $value, pos=$position)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isInplace: Boolean
|
||||||
|
get() {
|
||||||
|
val binExpr = value as? BinaryExpression
|
||||||
|
if(binExpr!=null) {
|
||||||
|
if(binExpr.left isSameAs target)
|
||||||
|
return true // A = A <operator> 5
|
||||||
|
|
||||||
|
if(binExpr.operator in associativeOperators) {
|
||||||
|
if (binExpr.right isSameAs target)
|
||||||
|
return true // A = v <associative-operator> A
|
||||||
|
|
||||||
|
val leftBinExpr = binExpr.left as? BinaryExpression
|
||||||
|
if(leftBinExpr?.operator == binExpr.operator) {
|
||||||
|
// A = (A <associative-operator> x) <same-operator> y
|
||||||
|
// A = (x <associative-operator> A) <same-operator> y
|
||||||
|
return leftBinExpr.left isSameAs target || leftBinExpr.right isSameAs target
|
||||||
|
}
|
||||||
|
val rightBinExpr = binExpr.right as? BinaryExpression
|
||||||
|
if(rightBinExpr?.operator == binExpr.operator) {
|
||||||
|
// A = y <associative-operator> (A <same-operator> x)
|
||||||
|
// A = y <associative-operator> (x <same-operator> y)
|
||||||
|
return rightBinExpr.left isSameAs target || rightBinExpr.right isSameAs target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AssignTarget(var identifier: IdentifierReference?,
|
data class AssignTarget(var identifier: IdentifierReference?,
|
||||||
|
@ -192,7 +192,7 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir:
|
|||||||
programAst.processAstBeforeAsmGeneration(errors)
|
programAst.processAstBeforeAsmGeneration(errors)
|
||||||
errors.handle()
|
errors.handle()
|
||||||
|
|
||||||
printAst(programAst) // TODO
|
// printAst(programAst)
|
||||||
|
|
||||||
val assembly = CompilationTarget.asmGenerator(
|
val assembly = CompilationTarget.asmGenerator(
|
||||||
programAst,
|
programAst,
|
||||||
|
@ -18,7 +18,9 @@ import prog8.compiler.toHex
|
|||||||
internal class AssignmentAsmGen(private val program: Program, private val errors: ErrorReporter, private val asmgen: AsmGen) {
|
internal class AssignmentAsmGen(private val program: Program, private val errors: ErrorReporter, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
internal fun translate(assign: Assignment) {
|
internal fun translate(assign: Assignment) {
|
||||||
// TODO check for in-place assignment A = A <operator> X and generate better code for that
|
if(assign.isInplace)
|
||||||
|
translateNormalAssignment(assign) // TODO generate better code here for in-place assignments
|
||||||
|
else
|
||||||
translateNormalAssignment(assign)
|
translateNormalAssignment(assign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +84,6 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
// TODO: (A +/- B) +/- C ==> A +/- ( B +/- C)
|
|
||||||
// TODO: (A * / B) * / C ==> A * / ( B * / C)
|
|
||||||
|
|
||||||
val leftVal = expr.left.constValue(program)
|
val leftVal = expr.left.constValue(program)
|
||||||
val rightVal = expr.right.constValue(program)
|
val rightVal = expr.right.constValue(program)
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ assignment: ``=``
|
|||||||
Note that an assignment sometimes is not possible or supported.
|
Note that an assignment sometimes is not possible or supported.
|
||||||
|
|
||||||
augmented assignment: ``+=`` ``-=`` ``*=`` ``/=`` ``**=`` ``&=`` ``|=`` ``^=`` ``<<=`` ``>>=``
|
augmented assignment: ``+=`` ``-=`` ``*=`` ``/=`` ``**=`` ``&=`` ``|=`` ``^=`` ``<<=`` ``>>=``
|
||||||
Syntactic sugar; ``aa += xx`` is equivalent to ``aa = aa + xx``
|
This is syntactic sugar; ``aa += xx`` is equivalent to ``aa = aa + xx``
|
||||||
|
|
||||||
postfix increment and decrement: ``++`` ``--``
|
postfix increment and decrement: ``++`` ``--``
|
||||||
Syntactic sugar; ``aa++`` is equivalent to ``aa = aa + 1``, and ``aa--`` is equivalent to ``aa = aa - 1``.
|
Syntactic sugar; ``aa++`` is equivalent to ``aa = aa + 1``, and ``aa--`` is equivalent to ``aa = aa - 1``.
|
||||||
|
@ -4,11 +4,6 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
|
|
||||||
; todo: add these to the Expression Simplifier so that all the below assignments become a simple in-place assignment:
|
|
||||||
; (A +/- B) +/- C ==> A +/- ( B +/- C)
|
|
||||||
; (A * / B) * / C ==> A * / ( B * / C)
|
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
@ -16,35 +11,37 @@ main {
|
|||||||
ubyte wv
|
ubyte wv
|
||||||
ubyte wv2
|
ubyte wv2
|
||||||
|
|
||||||
wv *= wv2
|
wv = wv + wv + wv
|
||||||
|
|
||||||
wv += 10
|
; wv *= wv2
|
||||||
wv += 20
|
;
|
||||||
wv += 30
|
; wv += 10
|
||||||
|
; wv += 20
|
||||||
wv += 1 + wv2
|
; wv += 30
|
||||||
wv += 2 + wv2
|
;
|
||||||
wv += 3 + wv2
|
; wv += 1 + wv2
|
||||||
|
; wv += 2 + wv2
|
||||||
wv += wv2 + 1
|
; wv += 3 + wv2
|
||||||
wv += wv2 + 2
|
;
|
||||||
wv += wv2 + 3
|
; wv += wv2 + 1
|
||||||
|
; wv += wv2 + 2
|
||||||
wv = wv + 1 + wv2
|
; wv += wv2 + 3
|
||||||
wv = wv + 2 + wv2
|
;
|
||||||
wv = wv + 3 + wv2
|
; wv = wv + 1 + wv2
|
||||||
|
; wv = wv + 2 + wv2
|
||||||
wv = 1 + wv2 + wv
|
; wv = wv + 3 + wv2
|
||||||
wv = 2 + wv2 + wv
|
;
|
||||||
wv = 3 + wv2 + wv
|
; wv = 1 + wv2 + wv
|
||||||
|
; wv = 2 + wv2 + wv
|
||||||
wv = wv + wv2 + 1
|
; wv = 3 + wv2 + wv
|
||||||
wv = wv + wv2 + 2
|
;
|
||||||
wv = wv + wv2 + 3
|
; wv = wv + wv2 + 1
|
||||||
|
; wv = wv + wv2 + 2
|
||||||
wv = wv2 + 1 + wv
|
; wv = wv + wv2 + 3
|
||||||
wv = wv2 + 2 + wv
|
;
|
||||||
wv = wv2 + 3 + wv
|
; wv = wv2 + 1 + wv
|
||||||
|
; wv = wv2 + 2 + wv
|
||||||
|
; wv = wv2 + 3 + wv
|
||||||
|
|
||||||
wv = wv2 + wv + 1
|
wv = wv2 + wv + 1
|
||||||
wv = wv2 + wv + 2
|
wv = wv2 + wv + 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user