taking address of a split word array is no longer a fatal error but a warning and the array is turned back into a normal word array.

This commit is contained in:
Irmen de Jong 2024-11-01 20:18:31 +01:00
parent 925b9d845d
commit 89425088ce
4 changed files with 80 additions and 6 deletions

View File

@ -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<IAstModification>()
for(elt in array.value.filterIsInstance<IdentifierReference>()) {
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<IAstModification> {
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
)
}
}

View File

@ -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")
}
})

View File

@ -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.

View File

@ -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
}
}