diff --git a/.github/workflows/all-ci.yml b/.github/workflows/all-ci.yml index d26a76b18..59f72d37b 100644 --- a/.github/workflows/all-ci.yml +++ b/.github/workflows/all-ci.yml @@ -35,9 +35,11 @@ jobs: name: prog8-compiler-jar-zipped path: compiler/build/libs/*-all.jar + release: + runs-on: ubuntu-latest + steps: - name: Calculate hash uses: MCJack123/ghaction-generate-release-hashes@v4 - if: "github.event_name == 'release'" with: get-assets: true hash-type: sha256 @@ -45,7 +47,6 @@ jobs: - name: Upload hashes uses: actions/upload-artifact@v4 - if: "github.event_name == 'release'" with: name: Artifact Hashes path: hashes.txt diff --git a/codeCore/src/prog8/code/core/Operators.kt b/codeCore/src/prog8/code/core/Operators.kt index 70cc8e837..2b1658c06 100644 --- a/codeCore/src/prog8/code/core/Operators.kt +++ b/codeCore/src/prog8/code/core/Operators.kt @@ -1,6 +1,6 @@ package prog8.code.core -val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=", "and", "or", "xor") +val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=", "xor") // note: and,or are no longer associative because of Shortcircuit/McCarthy evaluation val ComparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=") val LogicalOperators = setOf("and", "or", "xor", "not", "in") val BitwiseOperators = setOf("&", "|", "^", "~") diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index c5c8e7572..2a691fe1c 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -4,7 +4,6 @@ import prog8.ast.* import prog8.ast.base.FatalAstException import prog8.ast.expressions.* import prog8.ast.statements.AnonymousScope -import prog8.ast.statements.Assignment import prog8.ast.statements.IfElse import prog8.ast.statements.Jump import prog8.ast.walk.AstWalker @@ -109,12 +108,6 @@ class ExpressionSimplifier(private val program: Program, private val options: Co if (!leftIDt.isKnown || !rightIDt.isKnown) throw FatalAstException("can't determine datatype of both expression operands $expr") - // NonBinaryExpression BinaryExpression --> BinaryExpression NonBinaryExpression - if (expr.operator in AssociativeOperators && expr.left !is BinaryExpression && expr.right is BinaryExpression) { - if(parent !is Assignment || !(expr.left isSameAs parent.target) && maySwapOperandOrder(expr)) - return listOf(IAstModification.SwapOperands(expr)) - } - // X + (-A) --> X - A if (expr.operator == "+" && (expr.right as? PrefixExpression)?.operator == "-") { return listOf(IAstModification.ReplaceNode( diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 45724c698..7c984dd1d 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -935,4 +935,41 @@ main { funcarg3.target.nameInSource shouldBe listOf("msb") funcarg3.args.single() shouldBe instanceOf() } + + test("no operand swap on logical expressions with shortcircuit evaluation") { + val src=""" +%import diskio +%zeropage basicsafe +%option no_sysinit + +main { + str scanline_buf = "?"* 20 + + sub start() { + if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ + + if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ + + if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ + } +}""" + val result = compileText(Cx16Target(), true, src, writeAssembly = false)!! + val st = result.compilerAst.entrypoint.statements + st.size shouldBe 3 + val ifCond1 = (st[0] as IfElse).condition as BinaryExpression + val ifCond2 = (st[1] as IfElse).condition as BinaryExpression + val ifCond3 = (st[2] as IfElse).condition as BinaryExpression + (ifCond1.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open") + (ifCond2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open") + (ifCond3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open") + val right1 = ifCond1.right as BinaryExpression + val right2 = ifCond2.right as BinaryExpression + val right3 = ifCond3.right as BinaryExpression + (right1.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read") + (right2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read") + (right3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read") + } }) diff --git a/examples/test.p8 b/examples/test.p8 index fb38e6ef2..2141683f4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,78 +1,18 @@ -%import textio -%import string +%import diskio %zeropage basicsafe +%option no_sysinit main { - sub start() { - str name = "irmen@de@jong" - cx16.r0L = findstr(name, "de-") - if_cs { - txt.print("found1. error. ") - } else { - txt.print("not found1. ok ") - } - txt.print_ub(cx16.r0L) - txt.nl() - txt.nl() - cx16.r0L = findstr(name, "de@") - if_cs { - txt.print("found2 (6?). ") - } else { - txt.print("not found2. error ") - } - txt.print_ub(cx16.r0L) - txt.nl() - txt.nl() - cx16.r0L = findstr(name, "irmen@de@jong") - if_cs { - txt.print("found3 (0?). ") - } else { - txt.print("not found3. error ") - } - txt.print_ub(cx16.r0L) - txt.nl() - txt.nl() - cx16.r0L = findstr(name, "irmen@de@jong1") - if_cs { - txt.print("found4. error. ") - } else { - txt.print("not found4. ok ") - } - txt.print_ub(cx16.r0L) - txt.nl() - txt.nl() - cx16.r0L = findstr(name, "jong") - if_cs { - txt.print("found5 (9?). ") - } else { - txt.print("not found5. error ") - } - txt.print_ub(cx16.r0L) - txt.nl() - txt.nl() - } + str scanline_buf = "?"* 20 - sub findstr(str haystack, str needle) -> ubyte { - ; searches for needle in haystack. - ; returns index in haystack where it first occurs, and Carry set, - ; or if needle doesn't occur in haystack it returns Carry clear and 255 (an invalid index.) - txt.print_uwhex(haystack, true) - txt.spc() - txt.print(haystack) - txt.nl() - cx16.r2L = string.length(haystack) - cx16.r3L = string.length(needle) - if cx16.r3L <= cx16.r2L { - cx16.r2L = cx16.r2L-cx16.r3L+1 - repeat cx16.r2L { - if string.startswith(haystack, needle) { - sys.set_carry() - return 13 as ubyte - } - haystack++ - } - } - sys.clear_carry() - return 255 + sub start() { + if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ + + if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ + + if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2 + cx16.r0++ } }