From 74db5c6be77949c254df4137d1b0a77b0eeb721b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 20 Nov 2021 17:33:02 +0100 Subject: [PATCH] fix referencesIdentifier() and better removal of unnecessary assignments --- .../optimizer/ConstantIdentifierReplacer.kt | 2 +- .../src/prog8/optimizer/UnusedCodeRemover.kt | 136 ++++++++++++++---- .../compiler/BeforeAsmGenerationAstChanger.kt | 2 +- compiler/src/prog8/compiler/Compiler.kt | 2 +- .../compiler/astprocessing/AstChecker.kt | 2 +- .../compiler/astprocessing/VariousCleanups.kt | 13 -- compiler/test/TestMemory.kt | 4 +- compiler/test/TestOptimization.kt | 96 ++++++++++--- compiler/test/TestSubroutines.kt | 1 - .../prog8/ast/expressions/AstExpressions.kt | 29 ++-- docs/source/todo.rst | 2 - examples/test.p8 | 74 +++++----- 12 files changed, 243 insertions(+), 120 deletions(-) diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 91424bea1..77ed595ef 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -111,7 +111,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private override fun before(decl: VarDecl, parent: Node): Iterable { // the initializer value can't refer to the variable itself (recursive definition) // TODO: use call graph for this? - if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true) { + if(decl.value?.referencesIdentifier(listOf(decl.name)) == true || decl.arraysize?.indexExpr?.referencesIdentifier(listOf(decl.name)) == true) { errors.err("recursive var declaration", decl.position) return noModifications } diff --git a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt index 98ce098eb..9e4f1f2de 100644 --- a/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/codeOptimizers/src/prog8/optimizer/UnusedCodeRemover.kt @@ -1,11 +1,9 @@ package prog8.optimizer import prog8.ast.* +import prog8.ast.base.DataType import prog8.ast.base.VarDeclType -import prog8.ast.expressions.BinaryExpression -import prog8.ast.expressions.FunctionCall -import prog8.ast.expressions.PrefixExpression -import prog8.ast.expressions.TypecastExpression +import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification @@ -58,8 +56,7 @@ class UnusedCodeRemover(private val program: Program, } override fun after(scope: AnonymousScope, parent: Node): Iterable { - val removeDoubleAssignments = deduplicateAssignments(scope.statements) - return removeDoubleAssignments.map { IAstModification.Remove(it, scope) } + return deduplicateAssignments(scope.statements, scope) } override fun after(block: Block, parent: Node): Iterable { @@ -75,8 +72,7 @@ class UnusedCodeRemover(private val program: Program, } } - val removeDoubleAssignments = deduplicateAssignments(block.statements) - return removeDoubleAssignments.map { IAstModification.Remove(it, block) } + return deduplicateAssignments(block.statements, block) } override fun after(subroutine: Subroutine, parent: Node): Iterable { @@ -99,8 +95,7 @@ class UnusedCodeRemover(private val program: Program, } } - val removeDoubleAssignments = deduplicateAssignments(subroutine.statements) - return removeDoubleAssignments.map { IAstModification.Remove(it, subroutine) } + return deduplicateAssignments(subroutine.statements, subroutine) } override fun after(decl: VarDecl, parent: Node): Iterable { @@ -135,28 +130,117 @@ class UnusedCodeRemover(private val program: Program, return noModifications } - private fun deduplicateAssignments(statements: List): List { + private fun deduplicateAssignments(statements: List, scope: IStatementContainer): List { // removes 'duplicate' assignments that assign the same target directly after another val linesToRemove = mutableListOf() + val modifications = mutableListOf() - for (stmtPairs in statements.windowed(2, step = 1)) { - val assign1 = stmtPairs[0] as? Assignment - val assign2 = stmtPairs[1] as? Assignment - if (assign1 != null && assign2 != null && !assign2.isAugmentable) { - if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) { - if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(*(assign2.target.identifier!!.nameInSource.toTypedArray()))) - // only remove the second assignment if its value is a simple expression! - when(assign2.value) { - is PrefixExpression, - is BinaryExpression, - is TypecastExpression, - is FunctionCall -> { /* don't remove */ } - else -> linesToRemove.add(assign1) - } + fun substituteZeroInBinexpr(expr: BinaryExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) { + if(expr.left isSameAs assign2.target) { + // X = X Right + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + expr.left, zero, expr + )) + } + if(expr.right isSameAs assign2.target) { + // X = Left X + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + expr.right, zero, expr + )) + } + val leftBinExpr = expr.left as? BinaryExpression + val rightBinExpr = expr.right as? BinaryExpression + if(leftBinExpr!=null && rightBinExpr==null) { + if(leftBinExpr.left isSameAs assign2.target) { + // X = (X Right) Something + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + leftBinExpr.left, zero, leftBinExpr + )) + } + if(leftBinExpr.right isSameAs assign2.target) { + // X = (Left X) Something + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + leftBinExpr.right, zero, leftBinExpr + )) + } + } + if(leftBinExpr==null && rightBinExpr!=null) { + if(rightBinExpr.left isSameAs assign2.target) { + // X = Something (X Right) + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + rightBinExpr.left, zero, rightBinExpr + )) + } + if(rightBinExpr.right isSameAs assign2.target) { + // X = Something (Left X) + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + rightBinExpr.right, zero, rightBinExpr + )) } } } - return linesToRemove + fun substituteZeroInPrefixexpr(expr: PrefixExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) { + if(expr.expression isSameAs assign2.target) { + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + expr.expression, zero, expr + )) + } + } + + fun substituteZeroInTypecast(expr: TypecastExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) { + if(expr.expression isSameAs assign2.target) { + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + expr.expression, zero, expr + )) + } + val subCast = expr.expression as? TypecastExpression + if(subCast!=null && subCast.expression isSameAs assign2.target) { + linesToRemove.add(assign1) + modifications.add(IAstModification.ReplaceNode( + subCast.expression, zero, subCast + )) + } + } + + for (stmtPairs in statements.windowed(2, step = 1)) { + val assign1 = stmtPairs[0] as? Assignment + val assign2 = stmtPairs[1] as? Assignment + if (assign1 != null && assign2 != null) { + val cvalue1 = assign1.value.constValue(program) + if(cvalue1!=null && cvalue1.number==0.0 && assign2.isAugmentable) { + val value2 = assign2.value + val zero = VarDecl.defaultZero(value2.inferType(program).getOr(DataType.UNDEFINED), value2.position) + when(value2) { + is BinaryExpression -> substituteZeroInBinexpr(value2, zero, assign1, assign2) + is PrefixExpression -> substituteZeroInPrefixexpr(value2, zero, assign1, assign2) + is TypecastExpression -> substituteZeroInTypecast(value2, zero, assign1, assign2) + else -> {} + } + } else { + if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) { + if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(assign2.target.identifier!!.nameInSource)) + // only remove the second assignment if its value is a simple expression! + when(assign2.value) { + is PrefixExpression, + is BinaryExpression, + is TypecastExpression, + is FunctionCall -> { /* don't remove */ } + else -> linesToRemove.add(assign1) + } + } + } + } + } + + return modifications + linesToRemove.map { IAstModification.Remove(it, scope) } } } diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 5e879184d..9a7f3064e 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -40,7 +40,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o if (binExpr != null && binExpr.operator !in comparisonOperators) { if (binExpr.left !is BinaryExpression) { - if (binExpr.right.referencesIdentifier(*assignment.target.identifier!!.nameInSource.toTypedArray())) { + if (binExpr.right.referencesIdentifier(assignment.target.identifier!!.nameInSource)) { // the right part of the expression contains the target variable itself. // we can't 'split' it trivially because the variable will be changed halfway through. if(binExpr.operator in associativeOperators) { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 0d2d99f88..5a2df381d 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -351,7 +351,7 @@ private fun writeAssembly(program: Program, } } -fun printAst(program: Program) { +fun printProgram(program: Program) { println() val printer = AstToSourceTextConverter(::print, program) printer.visit(program) diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index c2b7e43c9..df24cb507 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -508,7 +508,7 @@ internal class AstChecker(private val program: Program, fun err(msg: String) = errors.err(msg, decl.position) // the initializer value can't refer to the variable itself (recursive definition) - if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true) + if(decl.value?.referencesIdentifier(listOf(decl.name)) == true || decl.arraysize?.indexExpr?.referencesIdentifier(listOf(decl.name)) == true) err("recursive var declaration") // CONST can only occur on simple types (byte, word, float) diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index 51b3b23c2..9a87b52c2 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -97,21 +97,8 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) val nextAssign = assignment.nextSibling() as? Assignment 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??? as long as there isn't a function call in the value! - if(nextAssign.value isSameAs assignment.value) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer)) - - if((assignment.value as? NumericLiteralValue)?.number==0.0 && nextAssign.isAugmentable) { - val value = nextAssign.value as BinaryExpression - if(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 diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index 4890b0947..3eb982856 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.PrefixExpression import prog8.ast.statements.* -import prog8.compiler.printAst +import prog8.compiler.printProgram import prog8.compiler.target.C64Target import prog8.compilerinterface.isIOAddress import prog8.parser.SourceCode @@ -144,7 +144,7 @@ class TestMemory: FunSpec({ target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) wrapWithProgram(listOf(assign)) - printAst(target.definingModule.program) + printProgram(target.definingModule.program) target.isIOAddress(C64Target.machine) shouldBe true } diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 68e48fbeb..7f643acd3 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -15,6 +15,7 @@ import prog8.ast.base.Position import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.compiler.BeforeAsmGenerationAstChanger +import prog8.compiler.printProgram import prog8.compiler.target.C64Target import prog8.compilerinterface.* import prog8tests.helpers.* @@ -344,9 +345,15 @@ class TestOptimization: FunSpec({ ubyte @shared z1 z1 = 10 ubyte @shared z2 - z2 = z1+z2+5 + z2 = ~z2 ubyte @shared z3 - z3 = z1+z3-5 + z3 = not z3 + uword @shared z4 + z4 = (z4 as ubyte) + ubyte @shared z5 + z5 = z1+z5+5 + ubyte @shared z6 + z6 = z1+z6-5 } }""" val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess() @@ -354,35 +361,53 @@ class TestOptimization: FunSpec({ ubyte z1 z1 = 10 ubyte z2 - z2 = z1 - z2 += 5 + z2 = 255 ubyte z3 - z3 = z1 - z3 -= 5 - */ + z3 = 1 + uword z4 + z4 = 0 + ubyte z5 + z5 = z1 + z5 += 5 + ubyte z6 + z6 = z1 + z6 -= 5 + */ val statements = result.program.entrypoint.statements - statements.size shouldBe 8 + statements.size shouldBe 14 val z1decl = statements[0] as VarDecl val z1init = statements[1] as Assignment val z2decl = statements[2] as VarDecl val z2init = statements[3] as Assignment - val z2plus = statements[4] as Assignment - val z3decl = statements[5] as VarDecl - val z3init = statements[6] as Assignment - val z3plus = statements[7] as Assignment + val z3decl = statements[4] as VarDecl + val z3init = statements[5] as Assignment + val z4decl = statements[6] as VarDecl + val z4init = statements[7] as Assignment + val z5decl = statements[8] as VarDecl + val z5init = statements[9] as Assignment + val z5plus = statements[10] as Assignment + val z6decl = statements[11] as VarDecl + val z6init = statements[12] as Assignment + val z6plus = statements[13] as Assignment z1decl.name shouldBe "z1" z1init.value shouldBe NumericLiteralValue(DataType.UBYTE, 10.0, Position.DUMMY) z2decl.name shouldBe "z2" - z2init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY) - z2plus.isAugmentable shouldBe true - (z2plus.value as BinaryExpression).operator shouldBe "+" - (z2plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY) + z2init.value shouldBe NumericLiteralValue(DataType.UBYTE, 255.0, Position.DUMMY) z3decl.name shouldBe "z3" - 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) + z3init.value shouldBe NumericLiteralValue(DataType.UBYTE, 1.0, Position.DUMMY) + z4decl.name shouldBe "z4" + z4init.value shouldBe NumericLiteralValue(DataType.UBYTE, 0.0, Position.DUMMY) + z5decl.name shouldBe "z5" + z5init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY) + z5plus.isAugmentable shouldBe true + (z5plus.value as BinaryExpression).operator shouldBe "+" + (z5plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY) + z6decl.name shouldBe "z6" + z6init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY) + z6plus.isAugmentable shouldBe true + (z6plus.value as BinaryExpression).operator shouldBe "-" + (z6plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY) } test("force_output option should work with optimizing memwrite assignment") { @@ -472,4 +497,35 @@ class TestOptimization: FunSpec({ val result = compileText(C64Target, optimize=false, src, writeAssembly=true).assertSuccess() result.program.entrypoint.statements.size shouldBe 10 } + + test("keep the value initializer assignment if the next one depends on it") { + val src=""" + main { + sub start() { + uword @shared yy + yy = 20 ; ok to remove =0 initializer before this + 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 + } + } + """ + 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 8 + stmts.filterIsInstance().size shouldBe 3 + stmts.filterIsInstance().size shouldBe 5 + } }) diff --git a/compiler/test/TestSubroutines.kt b/compiler/test/TestSubroutines.kt index 38eaa8897..7bf4de318 100644 --- a/compiler/test/TestSubroutines.kt +++ b/compiler/test/TestSubroutines.kt @@ -9,7 +9,6 @@ import io.kotest.matchers.types.instanceOf import prog8.ast.base.DataType import prog8.ast.expressions.* import prog8.ast.statements.* -import prog8.compiler.printAst import prog8.compiler.target.C64Target import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.assertFailure diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index bd3a0dcf6..11f50a5fb 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -22,7 +22,7 @@ sealed class Expression: Node { abstract fun constValue(program: Program): NumericLiteralValue? abstract fun accept(visitor: IAstVisitor) abstract fun accept(visitor: AstWalker, parent: Node) - abstract fun referencesIdentifier(vararg scopedName: String): Boolean + abstract fun referencesIdentifier(nameInSource: List): Boolean abstract fun inferType(program: Program): InferredTypes.InferredType abstract val isSimple: Boolean @@ -123,7 +123,7 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String) = expression.referencesIdentifier(*scopedName) + override fun referencesIdentifier(nameInSource: List) = expression.referencesIdentifier(nameInSource) override fun inferType(program: Program): InferredTypes.InferredType { val inferred = expression.inferType(program) return when(operator) { @@ -183,7 +183,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String) = left.referencesIdentifier(*scopedName) || right.referencesIdentifier(*scopedName) + override fun referencesIdentifier(nameInSource: List) = left.referencesIdentifier(nameInSource) || right.referencesIdentifier(nameInSource) override fun inferType(program: Program): InferredTypes.InferredType { val leftDt = left.inferType(program) val rightDt = right.inferType(program) @@ -300,7 +300,7 @@ class ArrayIndexedExpression(var arrayvar: IdentifierReference, override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String) = arrayvar.referencesIdentifier(*scopedName) + override fun referencesIdentifier(nameInSource: List) = arrayvar.referencesIdentifier(nameInSource) override fun inferType(program: Program): InferredTypes.InferredType { val target = arrayvar.targetStatement(program) @@ -341,7 +341,7 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String) = expression.referencesIdentifier(*scopedName) + override fun referencesIdentifier(nameInSource: List) = expression.referencesIdentifier(nameInSource) override fun inferType(program: Program) = InferredTypes.knownFor(type) override fun constValue(program: Program): NumericLiteralValue? { val cv = expression.constValue(program) ?: return null @@ -378,7 +378,7 @@ data class AddressOf(var identifier: IdentifierReference, override val position: override fun copy() = AddressOf(identifier.copy(), position) override fun constValue(program: Program): NumericLiteralValue? = null - override fun referencesIdentifier(vararg scopedName: String) = false + override fun referencesIdentifier(nameInSource: List) = identifier.nameInSource==nameInSource override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UWORD) override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) @@ -404,7 +404,7 @@ class DirectMemoryRead(var addressExpression: Expression, override val position: override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String) = false + override fun referencesIdentifier(nameInSource: List) = addressExpression.referencesIdentifier(nameInSource) override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UBYTE) override fun constValue(program: Program): NumericLiteralValue? = null @@ -472,7 +472,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed throw FatalAstException("can't replace here") } - override fun referencesIdentifier(vararg scopedName: String) = false + override fun referencesIdentifier(nameInSource: List) = false override fun constValue(program: Program) = this override fun accept(visitor: IAstVisitor) = visitor.visit(this) @@ -579,7 +579,7 @@ class CharLiteral(val value: Char, } override fun copy() = CharLiteral(value, altEncoding, position) - override fun referencesIdentifier(vararg scopedName: String) = false + override fun referencesIdentifier(nameInSource: List) = false override fun constValue(program: Program): NumericLiteralValue { val bytevalue = program.encoding.encodeString(value.toString(), altEncoding).single() return NumericLiteralValue(DataType.UBYTE, bytevalue.toDouble(), position) @@ -614,7 +614,7 @@ class StringLiteralValue(val value: String, throw FatalAstException("can't replace here") } - override fun referencesIdentifier(vararg scopedName: String) = false + override fun referencesIdentifier(nameInSource: List) = false override fun constValue(program: Program): NumericLiteralValue? = null override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) @@ -650,7 +650,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be replacement.parent = this } - override fun referencesIdentifier(vararg scopedName: String) = value.any { it.referencesIdentifier(*scopedName) } + override fun referencesIdentifier(nameInSource: List) = value.any { it.referencesIdentifier(nameInSource) } override fun constValue(program: Program): NumericLiteralValue? = null override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) @@ -757,7 +757,7 @@ class RangeExpr(var from: Expression, override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String): Boolean = from.referencesIdentifier(*scopedName) || to.referencesIdentifier(*scopedName) + override fun referencesIdentifier(nameInSource: List): Boolean = from.referencesIdentifier(nameInSource) || to.referencesIdentifier(nameInSource) override fun inferType(program: Program): InferredTypes.InferredType { val fromDt=from.inferType(program) val toDt=to.inferType(program) @@ -829,8 +829,7 @@ data class IdentifierReference(val nameInSource: List, override val posi override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String): Boolean = - nameInSource.size==scopedName.size && nameInSource.toTypedArray().contentEquals(scopedName) + override fun referencesIdentifier(nameInSource: List): Boolean = this.nameInSource==nameInSource override fun inferType(program: Program): InferredTypes.InferredType { return when (val targetStmt = targetStatement(program)) { @@ -899,7 +898,7 @@ class FunctionCall(override var target: IdentifierReference, override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) - override fun referencesIdentifier(vararg scopedName: String): Boolean = target.referencesIdentifier(*scopedName) || args.any{it.referencesIdentifier(*scopedName)} + override fun referencesIdentifier(nameInSource: List): Boolean = target.referencesIdentifier(nameInSource) || args.any{it.referencesIdentifier(nameInSource)} override fun inferType(program: Program): InferredTypes.InferredType { val constVal = constValue(program ,false) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 60a01417c..fd0d98146 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -5,8 +5,6 @@ For next compiler release (7.4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fix "test augmented expression asmgen" unittest (and textelite compilation) -TODO certain typecast expressions are also augmentable?? what does this even mean, and does the generated code make a difference??? - optimize TODO in "Add assignment to initialize with zero" in StatementReorderer optimize TODO in after(assignment) in VariousCleanups optimize: add some more constant folders mentioned in test.p8 diff --git a/examples/test.p8 b/examples/test.p8 index fddf9836f..2247c11b4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -11,42 +11,42 @@ main { byte bb float fl -; TODO add these constant folders: - -; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2) -; (X + C1) - (Y + C2) => (X - Y) + (C1 - C2) -; ---> together: (X + C1) (Y + C2) => (X Y) + (C1 C2) - - -; (X - C1) + (Y - C2) => (X + Y) - (C1 + C2) -; (X - C1) - (Y - C2) => (X - Y) - (C1 - C2) - - xx=6 - yy=8 - - yy = (xx+5)+(yy+10) - txt.print_ub(yy) ; 29 - txt.nl() - - xx=100 - yy=8 - yy = (xx+5)-(yy+10) - txt.print_ub(yy) ; 87 - txt.nl() - - xx=50 - yy=40 - yy = (xx-5)+(yy-10) - txt.print_ub(yy) ; 75 - txt.nl() - - xx=50 - yy=20 - yy = (xx-5)-(yy-10) - txt.print_ub(yy) ; 35 - txt.nl() - - repeat { - } +;; TODO add these constant folders: +; +;; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2) +;; (X + C1) - (Y + C2) => (X - Y) + (C1 - C2) +;; ---> together: (X + C1) (Y + C2) => (X Y) + (C1 C2) +; +; +;; (X - C1) + (Y - C2) => (X + Y) - (C1 + C2) +;; (X - C1) - (Y - C2) => (X - Y) - (C1 - C2) +; +; xx=6 +; yy=8 +; +; yy = (xx+5)+(yy+10) +; txt.print_ub(yy) ; 29 +; txt.nl() +; +; xx=100 +; yy=8 +; yy = (xx+5)-(yy+10) +; txt.print_ub(yy) ; 87 +; txt.nl() +; +; xx=50 +; yy=40 +; yy = (xx-5)+(yy-10) +; txt.print_ub(yy) ; 75 +; txt.nl() +; +; xx=50 +; yy=20 +; yy = (xx-5)-(yy-10) +; txt.print_ub(yy) ; 35 +; txt.nl() +; +; repeat { +; } } }