mirror of
https://github.com/irmen/prog8.git
synced 2025-03-01 00:30:03 +00:00
binexpr expression splitter for assignments
This commit is contained in:
parent
9cd3a9f8e8
commit
110f877dcc
@ -3,44 +3,44 @@ package prog8.optimizer
|
|||||||
import prog8.ast.INameScope
|
import prog8.ast.INameScope
|
||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
|
import prog8.ast.base.VarDeclType
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.processing.AstWalker
|
import prog8.ast.processing.AstWalker
|
||||||
import prog8.ast.processing.IAstModification
|
import prog8.ast.processing.IAstModification
|
||||||
import prog8.ast.statements.AssignTarget
|
import prog8.ast.statements.AssignTarget
|
||||||
import prog8.ast.statements.Assignment
|
import prog8.ast.statements.Assignment
|
||||||
|
import prog8.ast.statements.VarDecl
|
||||||
|
|
||||||
class ExpressionSplitter(private val program: Program) : AstWalker() {
|
class ExpressionSplitter(private val program: Program) : AstWalker() {
|
||||||
|
|
||||||
// TODO once this works, integrate it back into expressionsimplifier
|
// TODO once this works, integrate it back into expressionsimplifier
|
||||||
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
if(assignment!=null) {
|
val expr = decl.value as? BinaryExpression
|
||||||
val expr = assignment.value as? BinaryExpression
|
if (expr != null) {
|
||||||
if (expr != null) {
|
// reduce the complexity of a (binary) expression that has to be evaluated on the eval stack,
|
||||||
// reduce the complexity of a (binary) expression that has to be evaluated on the eval stack,
|
// by attempting to splitting it up into individual simple steps:
|
||||||
// by attempting to splitting it up into individual simple steps:
|
// X = <some-expression-not-X> <operator> <not-binary-expression>
|
||||||
// X = <some-expression-not-X> <operator> <not-binary-expression>
|
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
|
||||||
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
|
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression>
|
||||||
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression>
|
|
||||||
|
|
||||||
// TODO FIX THIS, IT SOMETIMES JUST LOOPS... (for example on plasma.p8)
|
// TODO DOES THIS LOOP AS WELL?
|
||||||
if (expr.operator !in comparisonOperators && !assignment.isAugmentable && isSimpleTarget(assignment.target, program.namespace)) {
|
if (expr.operator !in comparisonOperators && decl.type==VarDeclType.VAR) {
|
||||||
if (expr.right !is BinaryExpression) {
|
if (expr.right !is BinaryExpression) {
|
||||||
println("SPLIT RIGHT BINEXPR $expr")
|
println("SPLIT VARDECL RIGHT BINEXPR $expr") // TODO
|
||||||
val firstAssign = Assignment(assignment.target, expr.left, assignment.position)
|
// val firstAssign = Assignment(assignment.target, expr.left, assignment.position)
|
||||||
val augExpr = BinaryExpression(assignment.target.toExpression(), expr.operator, expr.right, expr.position)
|
// val augExpr = BinaryExpression(assignment.target.toExpression(), expr.operator, expr.right, expr.position)
|
||||||
return listOf(
|
// return listOf(
|
||||||
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
// IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
IAstModification.ReplaceNode(assignment.value, augExpr, assignment)
|
// IAstModification.ReplaceNode(assignment.value, augExpr, assignment)
|
||||||
)
|
// )
|
||||||
} else if (expr.left !is BinaryExpression && expr.operator in associativeOperators) {
|
} else if (expr.left !is BinaryExpression && expr.operator in associativeOperators) {
|
||||||
println("SPLIT LEFT BINEXPR $expr")
|
println("SPLIT VARDECL LEFT BINEXPR $expr") // TODO
|
||||||
val firstAssign = Assignment(assignment.target, expr.right, assignment.position)
|
// val firstAssign = Assignment(assignment.target, expr.right, assignment.position)
|
||||||
val augExpr = BinaryExpression(assignment.target.toExpression(), expr.operator, expr.left, expr.position)
|
// val augExpr = BinaryExpression(assignment.target.toExpression(), expr.operator, expr.left, expr.position)
|
||||||
return listOf(
|
// return listOf(
|
||||||
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
// IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
// IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,13 +48,73 @@ class ExpressionSplitter(private val program: Program) : AstWalker() {
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO once this works, integrate it back into expressionsimplifier
|
||||||
|
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
|
val binExpr = assignment.value as? BinaryExpression
|
||||||
|
if (binExpr != null) {
|
||||||
|
/*
|
||||||
|
|
||||||
|
reduce the complexity of a (binary) expression that has to be evaluated on the eval stack,
|
||||||
|
by attempting to splitting it up into individual simple steps:
|
||||||
|
|
||||||
|
|
||||||
|
X = BinExpr X = LeftExpr
|
||||||
|
<operator> followed by
|
||||||
|
/ \ IF 'X' not used X = BinExpr
|
||||||
|
/ \ IN LEFTEXPR ==> <operator>
|
||||||
|
/ \ / \
|
||||||
|
LeftExpr. RightExpr. / \
|
||||||
|
/ \ / \ X RightExpr.
|
||||||
|
.. .. .. ..
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
X = BinExpr X = RightExpr
|
||||||
|
<operator> followed by
|
||||||
|
/ \ IF ASSOCIATIVE X = BinExpr
|
||||||
|
/ \ <operator> ==> <operator>
|
||||||
|
/ \ / \
|
||||||
|
LeftExpr. SimpleExpr. / \
|
||||||
|
/ \ (not X) X LeftExpr.
|
||||||
|
.. ..
|
||||||
|
|
||||||
|
*/
|
||||||
|
if(!assignment.isAugmentable && isSimpleTarget(assignment.target, program.namespace)) {
|
||||||
|
val firstAssign = Assignment(assignment.target, binExpr.left, binExpr.left.position)
|
||||||
|
val targetExpr = assignment.target.toExpression()
|
||||||
|
val augExpr = BinaryExpression(targetExpr, binExpr.operator, binExpr.right, binExpr.right.position)
|
||||||
|
return listOf(
|
||||||
|
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
|
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
||||||
|
}
|
||||||
|
|
||||||
|
if(binExpr.operator in associativeOperators && binExpr.left is BinaryExpression) {
|
||||||
|
if (binExpr.right !is BinaryExpression && !(binExpr.right isSameAs assignment.target)) {
|
||||||
|
val firstAssign = Assignment(assignment.target, binExpr.right, binExpr.right.position)
|
||||||
|
val targetExpr = assignment.target.toExpression()
|
||||||
|
val augExpr = BinaryExpression(targetExpr, binExpr.operator, binExpr.left, binExpr.left.position)
|
||||||
|
return listOf(
|
||||||
|
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
|
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO further unraveling of binary expression trees into flat statements.
|
||||||
|
// however this should probably be done in a more generic way to also service
|
||||||
|
// the expressiontrees that are not used in an assignment statement...
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun isSimpleTarget(target: AssignTarget, namespace: INameScope): Boolean {
|
private fun isSimpleTarget(target: AssignTarget, namespace: INameScope): Boolean {
|
||||||
return when {
|
return when {
|
||||||
target.identifier!=null -> target.isInRegularRAM(namespace)
|
target.identifier!=null -> target.isInRegularRAM(namespace)
|
||||||
target.memoryAddress!=null -> target.isInRegularRAM(namespace)
|
target.memoryAddress!=null -> target.isInRegularRAM(namespace)
|
||||||
target.arrayindexed!=null -> {
|
target.arrayindexed!=null -> {
|
||||||
val index = target.arrayindexed!!.arrayspec.index
|
val index = target.arrayindexed!!.arrayspec.index
|
||||||
if(index is NumericLiteralValue || index is IdentifierReference)
|
if(index is NumericLiteralValue)
|
||||||
target.isInRegularRAM(namespace)
|
target.isInRegularRAM(namespace)
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
@ -55,8 +55,8 @@ internal fun Program.simplifyExpressions() : Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.splitExpressions() : Int {
|
internal fun Program.splitExpressions() : Int {
|
||||||
val opti = ExpressionSplitter(this)
|
val splitter = ExpressionSplitter(this)
|
||||||
opti.visit(this)
|
splitter.visit(this)
|
||||||
return opti.applyModifications()
|
return splitter.applyModifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,20 +19,20 @@ main {
|
|||||||
; uword[] arrays = [names, names3, values]
|
; uword[] arrays = [names, names3, values]
|
||||||
|
|
||||||
|
|
||||||
asmsub testX() {
|
; asmsub testX() {
|
||||||
%asm {{
|
; %asm {{
|
||||||
stx _saveX
|
; stx _saveX
|
||||||
lda #13
|
; lda #13
|
||||||
jsr txt.chrout
|
; jsr txt.chrout
|
||||||
lda _saveX
|
; lda _saveX
|
||||||
jsr txt.print_ub
|
; jsr txt.print_ub
|
||||||
lda #13
|
; lda #13
|
||||||
jsr txt.chrout
|
; jsr txt.chrout
|
||||||
ldx _saveX
|
; ldx _saveX
|
||||||
rts
|
; rts
|
||||||
_saveX .byte 0
|
;_saveX .byte 0
|
||||||
}}
|
; }}
|
||||||
}
|
; }
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
; byte bb = 100
|
; byte bb = 100
|
||||||
|
Loading…
x
Reference in New Issue
Block a user