diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 453f7bda5..2a0b7529f 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -44,6 +44,8 @@ fun compileProgram(filepath: Path, lateinit var program: Program lateinit var importedFiles: List + val optimizeFloatExpr = if(optimize) optimizeFloatExpressions else false + val compTarget = when(compilationTarget) { C64Target.name -> C64Target @@ -58,7 +60,7 @@ fun compileProgram(filepath: Path, with(compilationOptions) { this.slowCodegenWarnings = slowCodegenWarnings this.optimize = optimize - this.optimizeFloatExpressions = optimizeFloatExpressions + this.optimizeFloatExpressions = optimizeFloatExpr } program = programresult importedFiles = imported diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 1d2e7c068..1b12432d9 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -23,7 +23,7 @@ private val examplesDir = assumeDirectory(workingDir, "../examples") private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilationTarget) = compileProgram( filepath, optimize, - optimizeFloatExpressions = false, + optimizeFloatExpressions = true, writeAssembly = true, slowCodegenWarnings = false, quietAssembler = true, diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index e22271f78..65cb63b9e 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -15,16 +15,14 @@ import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.compiler.BeforeAsmGenerationAstChanger import prog8.compiler.target.C64Target -import prog8.compiler.target.c64.C64MachineDefinition -import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compilerinterface.* -import prog8tests.ast.helpers.outputDir import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyStringEncoder import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.assertSuccess import prog8tests.helpers.compileText +import prog8tests.helpers.generateAssembly class TestOptimization: FunSpec({ test("testRemoveEmptySubroutineExceptStart") { @@ -188,10 +186,34 @@ class TestOptimization: FunSpec({ (bbAssigns1expr.right as PrefixExpression).expression shouldBe IdentifierReference(listOf("ww"), Position.DUMMY) bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE - val zp = C64MachineDefinition.C64Zeropage(options) - options.compTarget.machine.zeropage=zp - val asmgen = AsmGen(result.program, ErrorReporterForTests(), zp, options, C64Target, outputDir) - val asm = asmgen.compileToAssembly() + val asm = generateAssembly(result.program, options) + asm.valid shouldBe true + } + + test("asmgen correctly deals with float typecasting in augmented assignment") { + val src=""" + %option enable_floats + + main { + sub start() { + ubyte ub + float ff + ff += (ub as float) ; operator doesn't matter + } + } + """ + val result1 = compileText(C64Target, optimize=false, src, writeAssembly = false).assertSuccess() + + // yy = (dy*(pixely as float) ) + val assignYY = result1.program.entrypoint.statements.last() as Assignment + assignYY.isAugmentable shouldBe true + assignYY.target.identifier!!.nameInSource shouldBe listOf("ff") + val value = assignYY.value as BinaryExpression + value.operator shouldBe "+" + value.left shouldBe IdentifierReference(listOf("ff"), Position.DUMMY) + value.right shouldBe instanceOf() + + val asm = generateAssembly(result1.program) asm.valid shouldBe true } }) diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index 79d208929..80fb0084c 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -2,10 +2,13 @@ package prog8tests.helpers import io.kotest.assertions.withClue import io.kotest.matchers.shouldBe +import prog8.ast.Program import prog8.compiler.CompilationResult import prog8.compiler.compileProgram -import prog8.compilerinterface.ICompilationTarget -import prog8.compilerinterface.IErrorReporter +import prog8.compiler.target.C64Target +import prog8.compiler.target.c64.C64MachineDefinition +import prog8.compiler.target.cpu6502.codegen.AsmGen +import prog8.compilerinterface.* import prog8tests.ast.helpers.assumeReadableFile import prog8tests.ast.helpers.outputDir import java.nio.file.Path @@ -37,14 +40,15 @@ internal fun compileFile( fileName: String, outputDir: Path = prog8tests.ast.helpers.outputDir, errors: IErrorReporter? = null, - writeAssembly: Boolean = true + writeAssembly: Boolean = true, + optFloatExpr: Boolean = true ) : CompilationResult { val filepath = fileDir.resolve(fileName) assumeReadableFile(filepath) return compileProgram( filepath, optimize, - optimizeFloatExpressions = false, + optimizeFloatExpressions = optFloatExpr, writeAssembly = writeAssembly, slowCodegenWarnings = false, quietAssembler = true, @@ -65,10 +69,23 @@ internal fun compileText( optimize: Boolean, sourceText: String, errors: IErrorReporter? = null, - writeAssembly: Boolean = true + writeAssembly: Boolean = true, + optFloatExpr: Boolean = true ) : CompilationResult { val filePath = outputDir.resolve("on_the_fly_test_" + sourceText.hashCode().toUInt().toString(16) + ".p8") // we don't assumeNotExists(filePath) - should be ok to just overwrite it filePath.toFile().writeText(sourceText) - return compileFile(platform, optimize, filePath.parent, filePath.name, errors=errors, writeAssembly=writeAssembly) + return compileFile(platform, optimize, filePath.parent, filePath.name, errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr) +} + + +internal fun generateAssembly( + program: Program, + options: CompilationOptions? = null +): IAssemblyProgram { + val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target) + val zp = C64MachineDefinition.C64Zeropage(coptions) + coptions.compTarget.machine.zeropage=zp + val asmgen = AsmGen(program, ErrorReporterForTests(), zp, coptions, C64Target, outputDir) + return asmgen.compileToAssembly() } diff --git a/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt index e264a34e8..a671603a3 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt @@ -18,15 +18,15 @@ enum class ZeropageType { DONTUSE } -data class CompilationOptions(val output: OutputType, - val launcher: LauncherType, - val zeropage: ZeropageType, - val zpReserved: List, - val floats: Boolean, - val noSysInit: Boolean, - val compTarget: ICompilationTarget -) { - var slowCodegenWarnings = false - var optimize = false - var optimizeFloatExpressions = false -} +class CompilationOptions(val output: OutputType, + val launcher: LauncherType, + val zeropage: ZeropageType, + val zpReserved: List, + val floats: Boolean, + val noSysInit: Boolean, + val compTarget: ICompilationTarget, + // these are set based on command line arguments: + var slowCodegenWarnings: Boolean = false, + var optimize: Boolean = false, + var optimizeFloatExpressions: Boolean = false +) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 05f253804..46fce9234 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,8 @@ TODO For next compiler release (7.3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- fix float crash in mandelbrot-gfx-colors.p8 (unittest is being written) + - add cosr8, sinr8, cosr16 and sinr16 that take a degree 0..179 (= 0..359 in 2 degree steps) to more easily scale halves/quarters etc of a circle than possible with the ones that take 0..255 'degrees'.