diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt index 08a835faf..1dcfda72a 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt @@ -4,6 +4,7 @@ import prog8.ast.IFunctionCall import prog8.ast.IStatementContainer import prog8.ast.Node import prog8.ast.Program +import prog8.ast.base.FatalAstException import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.AstWalker @@ -76,6 +77,23 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro } } } + + if(array.type.isArray) { + val mods = mutableListOf() + for(elt in array.value.filterIsInstance()) { + val decl = elt.targetVarDecl(program) + if(decl!=null && decl.splitArray) { + // you can't take the adress of a split-word array. + // instead of giving a fatal error, we remove the + // instead of a fatal error, we give a warning and turn it back into a regular array. + errors.warn("cannot take address of split word array - the array is turned back into a regular word array", decl.position) + val normalArray = makeNormalArrayFromSplit(decl) + mods.add(IAstModification.ReplaceNode(decl, normalArray, decl.parent)) + } + } + return mods + } + return noModifications } @@ -138,4 +156,32 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro // } return noModifications } + + override fun after(addressOf: AddressOf, parent: Node): Iterable { + val variable=addressOf.identifier.targetVarDecl(program) + if (variable!=null) { + if (variable.splitArray) { + // you can't take the adress of a split-word array. + // instead of giving a fatal error, we remove the + // instead of a fatal error, we give a warning and turn it back into a regular array. + errors.warn("cannot take address of split word array - the array is turned back into a regular word array", addressOf.position) + val normalArray = makeNormalArrayFromSplit(variable) + return listOf(IAstModification.ReplaceNode(variable, normalArray, variable.parent)) + } + } + return noModifications + } + + private fun makeNormalArrayFromSplit(variable: VarDecl): VarDecl { + val normalDt = when(variable.datatype) { + DataType.ARRAY_UW_SPLIT -> DataType.ARRAY_UW + DataType.ARRAY_W_SPLIT -> DataType.ARRAY_W + else -> throw FatalAstException("invalid dt") + } + return VarDecl( + variable.type, variable.origin, normalDt, variable.zeropage, variable.arraysize, variable.name, emptyList(), + variable.value?.copy(), variable.sharedWithAsm, false, variable.alignment, variable.position + ) + } + } diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index ed445ff5b..1914295e5 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -795,5 +795,31 @@ txt { errors.errors[0] shouldContain "undefined symbol: txt.print2222" errors.errors[1] shouldContain "undefined symbol: txt.DEFAULT_WIDTH_XXX" } + + test("split arrays back to normal when address is taken") { + val src=""" +main { + sub start() { + cx16.r0L=0 + if cx16.r0L==0 { + uword[] addresses = [scores2, start] + uword[] @split scores1 = [10, 25, 50, 100] + uword[] @split scores2 = [100, 250, 500, 1000] + + cx16.r0 = &scores1 + cx16.r1 = &scores2 + cx16.r2 = &addresses + } + } +}""" + val errors = ErrorReporterForTests(keepMessagesAfterReporting = true) + compileText(C64Target(), optimize=false, src, writeAssembly=true, errors=errors) shouldNotBe null + errors.errors.size shouldBe 0 + errors.warnings.size shouldBe 2 + errors.warnings[0] shouldContain("address") + errors.warnings[1] shouldContain("address") + errors.warnings[0] shouldContain("split") + errors.warnings[1] shouldContain("split") + } }) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index cbc9371db..c2cb468d9 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,6 @@ TODO ==== -"cannot take address of split word array" -> don't make this a fatal error, make it a warning and turn the array into a regular array instead -(benchmark program/textelite should then be compilable with -splitarrays) - merge problem: if 2 library modules both have merge, stuff breaks (math & prog8_math where prog8_math used to have math block.... didn't work) for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed. diff --git a/examples/test.p8 b/examples/test.p8 index ae1b46d11..b65d69ce5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,10 +5,15 @@ main { sub start() { + cx16.r0L=0 if cx16.r0L==0 { - uword[] scores = [10, 25, 50, 100] ; can never clear more than 4 lines at once - txt.print_uw(scores[1]) - txt.nl() + uword[] addresses = [scores2, start] + uword[] @split scores1 = [10, 25, 50, 100] ; can never clear more than 4 lines at once + uword[] @split scores2 = [10, 25, 50, 100] ; can never clear more than 4 lines at once + + cx16.r0 = &scores1 + cx16.r1 = &scores2 + cx16.r2 = &addresses } }