diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index f7283c26b..6000abb74 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -113,10 +113,10 @@ class AsmGen( out(" lda $sourceName") return sourceName } - is PtVariable -> { + is PtVariable, is PtMemMapped -> { val sourceName = asmVariableName(pointervar) if (isTargetCpu(CpuType.CPU65c02)) { - return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string + return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string // pointervar is already in the zero page, no need to copy out(" lda ($sourceName)") sourceName @@ -130,7 +130,7 @@ class AsmGen( "P8ZP_SCRATCH_W1" } } else { - return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string + return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string // pointervar is already in the zero page, no need to copy out(" ldy #0 | lda ($sourceName),y") sourceName @@ -146,7 +146,7 @@ class AsmGen( } } } - else -> throw AssemblyError("invalid pointervar") + else -> throw AssemblyError("invalid pointervar $target") } } @@ -995,7 +995,7 @@ $repeatLabel lda $counterVar out(" lda ${asmSymbolName(pointervar)},y") return true } - is PtVariable, null -> { + is IPtVariable, null -> { if(write) { if(pointervar!=null && isZpVar(pointervar)) { val saveA = evalBytevalueWillClobberA(ptrAndIndex.second) @@ -1045,7 +1045,7 @@ $repeatLabel lda $counterVar } return true } - else -> throw AssemblyError("invalid pointervar") + else -> throw AssemblyError("invalid pointervar $pointervar") } } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt index 941c409a0..8279bd7e9 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/Extensions.kt @@ -162,3 +162,27 @@ internal fun IPtSubroutine.returnsWhatWhere(): List return withClonedChildrenFrom(this, PtAddressOf(position)) + is PtArray -> return withClonedChildrenFrom(this, PtArray(type, position)) + is PtArrayIndexer -> return withClonedChildrenFrom(this, PtArrayIndexer(type, position)) + is PtBinaryExpression -> return withClonedChildrenFrom(this, PtBinaryExpression(operator, type, position)) + is PtBuiltinFunctionCall -> return withClonedChildrenFrom(this, PtBuiltinFunctionCall(name, void, hasNoSideEffects, type, position)) + is PtContainmentCheck -> return withClonedChildrenFrom(this, PtContainmentCheck(position)) + is PtFunctionCall -> return withClonedChildrenFrom(this, PtFunctionCall(name, void, type, position)) + is PtIdentifier -> return withClonedChildrenFrom(this, PtIdentifier(name, type, position)) + is PtMachineRegister -> return withClonedChildrenFrom(this, PtMachineRegister(register, type, position)) + is PtMemoryByte -> return withClonedChildrenFrom(this, PtMemoryByte(position)) + is PtNumber -> return withClonedChildrenFrom(this, PtNumber(type, number, position)) + is PtPrefix -> return withClonedChildrenFrom(this, PtPrefix(operator, type, position)) + is PtRange -> return withClonedChildrenFrom(this, PtRange(type, position)) + is PtString -> return withClonedChildrenFrom(this, PtString(value, encoding, position)) + is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position)) + } +} \ No newline at end of file diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index e09b0813a..b02ce997b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -363,11 +363,12 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignTrue.add(assignment) val assignFalse = PtNodeGroup() val ifelse = PtIfElse(assign.position) - val exprClone = arrayOf(expr).clone()[0] - require(exprClone !== expr) // TODO remove check if it works - ifelse.add(expr) + val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position) + expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone + ifelse.add(exprClone) ifelse.add(assignTrue) ifelse.add(assignFalse) + ifelse.parent = expr.parent asmgen.translate(ifelse) return true } diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index 7446825a6..7c6491f5e 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -136,12 +136,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, options: Compilati internal fun Program.variousCleanups(errors: IErrorReporter, options: CompilationOptions) { val process = VariousCleanups(this, errors, options) process.visit(this) - if(errors.noErrors()) { - if(process.applyModifications()>0) { - process.visit(this) - if(errors.noErrors()) - process.applyModifications() - } + while(errors.noErrors() && process.applyModifications()>0) { // TODO limit the number of cycles here? + process.visit(this) } } diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index c6728b183..926197ee5 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -62,6 +62,11 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, } override fun after(assignment: Assignment, parent: Node): Iterable { + if(assignment.target isSameAs assignment.value) { + // remove assignment to self + return listOf(IAstModification.Remove(assignment, parent as IStatementContainer)) + } + // remove duplicated assignments, but not if it's a memory mapped IO register val isIO = try { assignment.target.isIOAddress(options.compTarget.machine) diff --git a/compiler/test/TestTypecasts.kt b/compiler/test/TestTypecasts.kt index 3f6673323..f119c9269 100644 --- a/compiler/test/TestTypecasts.kt +++ b/compiler/test/TestTypecasts.kt @@ -120,6 +120,42 @@ main { right3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY) } + test("simple logical with bool no typecast") { + val text=""" +main { + bool bb + + sub start() { + bb = bb and 123 + } +}""" + val result = compileText(C64Target(), true, text, writeAssembly = true)!! + val stmts = result.program.entrypoint.statements + stmts.size shouldBe 2 + val assignValue = (stmts[0] as Assignment).value as BinaryExpression + assignValue.left shouldBe instanceOf() + assignValue.operator shouldBe "&" + (assignValue.right as NumericLiteral).number shouldBe 1.0 + } + + test("simple logical with byte instead of bool ok with typecasting") { + val text=""" +main { + ubyte ubb + + sub start() { + ubb = ubb and 123 + } +}""" + val result = compileText(C64Target(), true, text, writeAssembly = true)!! + val stmts = result.program.entrypoint.statements + stmts.size shouldBe 2 + val assignValue = (stmts[0] as Assignment).value as BinaryExpression + assignValue.left shouldBe instanceOf() // as a result of the cast to boolean + assignValue.operator shouldBe "&" + (assignValue.right as NumericLiteral).number shouldBe 1.0 + } + test("logical with byte instead of bool") { val text=""" %import textio