From f2daa17b92a19713b01e6306ba9d60e8585af4e6 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 5 Jan 2024 15:31:45 +0100 Subject: [PATCH] tweak some not optimizations cleanup IR typestring --- .../prog8/optimizer/ExpressionSimplifier.kt | 20 ++++++++- .../src/prog8/optimizer/StatementOptimizer.kt | 2 +- .../compiler/astprocessing/BoolRemover.kt | 8 ++++ .../compiler/astprocessing/CodeDesugarer.kt | 4 +- ...NotExpressionAndIfComparisonExprChanger.kt | 11 ++--- compiler/test/ast/TestVariousCompilerAst.kt | 14 +++---- .../src/prog8/ast/AstToSourceTextConverter.kt | 9 +++- .../prog8/ast/expressions/AstExpressions.kt | 7 +++- docs/source/todo.rst | 6 --- .../src/prog8/intermediate/IRFileWriter.kt | 2 +- .../src/prog8/intermediate/IRSymbolTable.kt | 41 +++---------------- intermediate/src/prog8/intermediate/Utils.kt | 36 +++++++++------- 12 files changed, 81 insertions(+), 79 deletions(-) diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index c6925791e..c12c90450 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -66,7 +66,7 @@ class ExpressionSimplifier(private val program: Program, ) } if(elsepart.statements.singleOrNull() is Jump) { - val invertedCondition = invertCondition(ifElse.condition) + val invertedCondition = invertCondition(ifElse.condition, program) return listOf( IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse), IAstModification.InsertAfter(ifElse, truepart, parent as IStatementContainer), @@ -323,7 +323,7 @@ class ExpressionSimplifier(private val program: Program, return if (test) { listOf(IAstModification.ReplaceNode(expr, expr.left, parent)) } else { - listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left), parent)) + listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left, program), parent)) } } } @@ -334,6 +334,22 @@ class ExpressionSimplifier(private val program: Program, return noModifications } + override fun after(expr: PrefixExpression, parent: Node): Iterable { + if(expr.operator=="not") { + // not X Y -> X Y + val binExpr = expr.expression as? BinaryExpression + if(binExpr!=null) { + val invertedOperator = invertedComparisonOperator(binExpr.operator) + if(invertedOperator!=null) { + val inverted = BinaryExpression(binExpr.left, invertedOperator, binExpr.right, binExpr.position) + return listOf(IAstModification.ReplaceNode(expr, inverted, parent)) + } + } + } + return noModifications + } + + private fun applyAbsorptionLaws(expr: BinaryExpression): Expression? { val rightB = expr.right as? BinaryExpression if(rightB!=null) { diff --git a/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt b/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt index 045e51fc1..50fa7a258 100644 --- a/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt +++ b/codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt @@ -120,7 +120,7 @@ class StatementOptimizer(private val program: Program, return listOf( IAstModification.ReplaceNode(ifElse.elsepart, newElsePart, ifElse), IAstModification.ReplaceNode(ifElse.truepart, newTruePart, ifElse), - IAstModification.ReplaceNode(ifElse.condition, invertCondition(ifElse.condition), ifElse) + IAstModification.ReplaceNode(ifElse.condition, invertCondition(ifElse.condition, program), ifElse) ) } } diff --git a/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt b/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt index da752016e..5a9477268 100644 --- a/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt +++ b/compiler/src/prog8/compiler/astprocessing/BoolRemover.kt @@ -90,6 +90,14 @@ internal class BoolRemover(val program: Program) : AstWalker() { override fun after(expr: PrefixExpression, parent: Node): Iterable { if(expr.operator=="not") { + val binExpr = expr.expression as? BinaryExpression + if(binExpr!=null) { + val invertedOperator = invertedComparisonOperator(binExpr.operator) + if(invertedOperator!=null) { + val inverted = BinaryExpression(binExpr.left, invertedOperator, binExpr.right, binExpr.position) + return listOf(IAstModification.ReplaceNode(expr, inverted, parent)) + } + } val exprDt = expr.expression.inferType(program).getOrElse { throw FatalAstException("unknown dt") } val nonBoolDt = if(exprDt==DataType.BOOL) DataType.UBYTE else exprDt val equalZero = BinaryExpression(expr.expression, "==", NumericLiteral(nonBoolDt, 0.0, expr.expression.position), expr.expression.position) diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 6455480bd..23bbd2385 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -99,7 +99,7 @@ if not CONDITION val replacement = AnonymousScope(mutableListOf( loopLabel, untilLoop.body, - IfElse(invertCondition(untilLoop.condition), + IfElse(invertCondition(untilLoop.condition, program), AnonymousScope(mutableListOf(program.jumpLabel(loopLabel)), pos), AnonymousScope(mutableListOf(), pos), pos) @@ -138,7 +138,7 @@ _after: val afterLabel = program.makeLabel("afterwhile", pos) val replacement = AnonymousScope(mutableListOf( loopLabel, - IfElse(invertCondition(whileLoop.condition), + IfElse(invertCondition(whileLoop.condition, program), AnonymousScope(mutableListOf(program.jumpLabel(afterLabel)), pos), AnonymousScope(mutableListOf(), pos), pos), diff --git a/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt b/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt index 3e3e0025c..d607c3f8f 100644 --- a/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt @@ -45,7 +45,7 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val if(expr.operator=="^" && expr.left.inferType(program) istype DataType.BOOL && expr.right.constValue(program)?.number == 1.0) { // boolean ^ 1 --> not boolean - return listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left), parent)) + return listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left, program), parent)) } @@ -121,10 +121,11 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val } } - // all other not(x) --> x==0 - // this means that "not" will never occur anywhere again in the ast after this - val replacement = BinaryExpression(expr.expression, "==", NumericLiteral(DataType.UBYTE,0.0, expr.position), expr.position) - return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent)) + // not simpleX -> simpleX==0 + if(expr.expression.isSimple) { + val replacement = BinaryExpression(expr.expression.copy(),"==", NumericLiteral(DataType.UBYTE, 0.0, expr.position), expr.position) + return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent)) + } } return noModifications } diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index bebab9fa1..8fe770f52 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -211,14 +211,12 @@ main { val result = compileText(C64Target(), optimize=false, src, writeAssembly=false)!! val stmts = result.compilerAst.entrypoint.statements stmts.size shouldBe 3 - val value1 = (stmts[1] as Assignment).value as BinaryExpression - val value2 = (stmts[2] as Assignment).value as BinaryExpression - value1.operator shouldBe "==" - value1.left shouldBe instanceOf() - (value1.right as NumericLiteral).number shouldBe 0.0 - value2.operator shouldBe "==" - value2.left shouldBe instanceOf() - (value2.right as NumericLiteral).number shouldBe 0.0 + val value1 = (stmts[1] as Assignment).value as PrefixExpression + val value2 = (stmts[2] as Assignment).value as PrefixExpression + value1.operator shouldBe "not" + value2.operator shouldBe "not" + value1.expression shouldBe instanceOf() + value2.expression shouldBe instanceOf() } test("const pointer variable indexing works") { diff --git a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt index 8d261cd5f..c63cf9a04 100644 --- a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt +++ b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt @@ -94,8 +94,13 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program: private fun datatypeString(dt: DataType): String { return when (dt) { - in NumericDatatypes -> dt.toString().lowercase() DataType.BOOL -> "bool" + DataType.UBYTE -> "ubyte" + DataType.BYTE -> "byte" + DataType.UWORD -> "uword" + DataType.WORD -> "word" + DataType.LONG -> "long" + DataType.FLOAT -> "float" DataType.STR -> "str" DataType.ARRAY_UB -> "ubyte[" DataType.ARRAY_B -> "byte[" @@ -105,7 +110,7 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program: DataType.ARRAY_BOOL -> "bool[" DataType.ARRAY_UW_SPLIT -> "@split uword[" DataType.ARRAY_W_SPLIT -> "@split word[" - else -> throw IllegalArgumentException("weird dt: $dt") + DataType.UNDEFINED -> throw IllegalArgumentException("wrong dt") } } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 8ab5b2e82..f48dbccb0 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -1257,12 +1257,15 @@ class BuiltinFunctionCall(override var target: IdentifierReference, override fun inferType(program: Program) = program.builtinFunctions.returnType(name) } -fun invertCondition(cond: Expression): Expression { +fun invertCondition(cond: Expression, program: Program): Expression { if(cond is BinaryExpression) { val invertedOperator = invertedComparisonOperator(cond.operator) if (invertedOperator != null) return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position) } - return PrefixExpression("not", cond, cond.position) + return if(cond.inferType(program).isBool) + PrefixExpression("not", cond, cond.position) + else + BinaryExpression(cond, "==", NumericLiteral(DataType.UBYTE, 0.0, cond.position), cond.position) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 9d98acd1e..9e48ab350 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,12 +1,6 @@ TODO ==== -consolidate the various type-to-string tables, look for: DataType.BOOL -> "bool" - -"all other not(x) --> x==0" SOMETIMES if removed, improves code, sometimes it makes it worse. - Find out what is what! (paint) - ALSO: when adding a expr.issimple to that, it crashes with a parent node mismatch error. FIX THAT. - ... diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index 8972e0127..d5dfddf24 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -105,7 +105,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) { xml.writeCharacters("\n") xml.writeStartElement("PARAMS") xml.writeCharacters("\n") - child.parameters.forEach { param -> xml.writeCharacters("${getTypeString(param.dt)} ${param.name}\n") } + child.parameters.forEach { param -> xml.writeCharacters("${param.dt.typeString(null)} ${param.name}\n") } xml.writeEndElement() xml.writeCharacters("\n") child.chunks.forEach { chunk -> diff --git a/intermediate/src/prog8/intermediate/IRSymbolTable.kt b/intermediate/src/prog8/intermediate/IRSymbolTable.kt index c6e3bd4cf..ccf9985b0 100644 --- a/intermediate/src/prog8/intermediate/IRSymbolTable.kt +++ b/intermediate/src/prog8/intermediate/IRSymbolTable.kt @@ -1,7 +1,10 @@ package prog8.intermediate import prog8.code.* -import prog8.code.core.* +import prog8.code.core.DataType +import prog8.code.core.Encoding +import prog8.code.core.ZeropageWish +import prog8.code.core.internedStringsModuleName // In the Intermediate Representation, all nesting has been removed. @@ -163,23 +166,7 @@ class IRStMemVar(name: String, } } - val typeString: String - get() = when (dt) { - DataType.BOOL -> "bool" - DataType.UBYTE -> "ubyte" - DataType.BYTE -> "byte" - DataType.UWORD -> "uword" - DataType.WORD -> "word" - DataType.FLOAT -> "float" - DataType.ARRAY_BOOL -> "bool[$length]" - DataType.ARRAY_UB, DataType.STR -> "ubyte[$length]" - DataType.ARRAY_B -> "byte[$length]" - DataType.ARRAY_UW -> "uword[$length]" - DataType.ARRAY_W -> "word[$length]" - DataType.ARRAY_F -> "float[$length]" - in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays") - else -> throw InternalCompilerException("weird dt") - } + val typeString: String = dt.typeString(length) } class IRStMemorySlab( @@ -220,23 +207,7 @@ class IRStStaticVariable(name: String, val uninitialized = onetimeInitializationArrayValue==null && onetimeInitializationStringValue==null && onetimeInitializationNumericValue==null - val typeString: String - get() = when (dt) { - DataType.BOOL -> "bool" - DataType.UBYTE -> "ubyte" - DataType.BYTE -> "byte" - DataType.UWORD -> "uword" - DataType.WORD -> "word" - DataType.FLOAT -> "float" - DataType.ARRAY_BOOL -> "bool[$length]" - DataType.ARRAY_UB, DataType.STR -> "ubyte[$length]" - DataType.ARRAY_B -> "byte[$length]" - DataType.ARRAY_UW -> "uword[$length]" - DataType.ARRAY_W -> "word[$length]" - DataType.ARRAY_F -> "float[$length]" - in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays") - else -> throw InternalCompilerException("weird dt") - } + val typeString: String = dt.typeString(length) } class IRStArrayElement(val number: Double?, val addressOfSymbol: String?) { diff --git a/intermediate/src/prog8/intermediate/Utils.kt b/intermediate/src/prog8/intermediate/Utils.kt index f023867c3..0d2c70d1b 100644 --- a/intermediate/src/prog8/intermediate/Utils.kt +++ b/intermediate/src/prog8/intermediate/Utils.kt @@ -6,21 +6,27 @@ import prog8.code.left import prog8.code.right -fun getTypeString(dt : DataType): String = when(dt) { - DataType.BOOL -> "bool" - DataType.UBYTE -> "ubyte" - DataType.BYTE -> "byte" - DataType.UWORD -> "uword" - DataType.WORD -> "word" - DataType.FLOAT -> "float" - DataType.ARRAY_BOOL -> "bool[]" - DataType.ARRAY_UB, DataType.STR -> "ubyte[]" - DataType.ARRAY_B -> "byte[]" - DataType.ARRAY_UW -> "uword[]" - DataType.ARRAY_W -> "word[]" - DataType.ARRAY_F -> "float[]" - in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays") - else -> throw InternalCompilerException("weird dt") +fun DataType.typeString(length: Int?): String { + val lengthStr = if(length==0) "" else length.toString() + return when (this) { + DataType.BOOL -> "bool" + DataType.UBYTE -> "ubyte" + DataType.BYTE -> "byte" + DataType.UWORD -> "uword" + DataType.WORD -> "word" + DataType.LONG -> "long" + DataType.FLOAT -> "float" + DataType.STR -> "ubyte[$lengthStr]" // here string doesn't exist as a seperate datatype anymore + DataType.ARRAY_BOOL -> "bool[$lengthStr]" + DataType.ARRAY_UB -> "ubyte[$lengthStr]" + DataType.ARRAY_B -> "byte[$lengthStr]" + DataType.ARRAY_UW -> "uword[$lengthStr]" + DataType.ARRAY_W -> "word[$lengthStr]" + DataType.ARRAY_F -> "float[$lengthStr]" + DataType.ARRAY_UW_SPLIT -> "@split uword[$lengthStr]" // should be 2 separate byte arrays by now really + DataType.ARRAY_W_SPLIT -> "@split word[$lengthStr]" // should be 2 separate byte arrays by now really + DataType.UNDEFINED -> throw IllegalArgumentException("wrong dt") + } } fun convertIRType(typestr: String): IRDataType? {