attempt to fix forloop range datatype issues

This commit is contained in:
Irmen de Jong 2024-10-03 20:44:18 +02:00
parent bf33a4f82d
commit 51279a98b3
5 changed files with 83 additions and 19 deletions

View File

@ -222,8 +222,8 @@ internal class AstChecker(private val program: Program,
}
DataType.WORD -> {
if(iterableDt!= DataType.BYTE && iterableDt!= DataType.WORD &&
iterableDt != DataType.ARRAY_B && iterableDt!= DataType.ARRAY_W &&
iterableDt != DataType.ARRAY_W_SPLIT)
iterableDt != DataType.ARRAY_B && iterableDt != DataType.ARRAY_UB &&
iterableDt != DataType.ARRAY_W && iterableDt != DataType.ARRAY_W_SPLIT)
errors.err("word loop variable can only loop over bytes or words", forLoop.position)
}
DataType.FLOAT -> {
@ -242,7 +242,7 @@ internal class AstChecker(private val program: Program,
val to = range.to as? NumericLiteral
if(from != null)
checkValueTypeAndRange(loopvar.datatype, from)
else if(range.from.inferType(program) isnot loopvar.datatype)
else if(range.from.inferType(program).isNotAssignableTo(loopvar.datatype))
errors.err("range start value is incompatible with loop variable type", range.position)
if(to != null)
checkValueTypeAndRange(loopvar.datatype, to)

View File

@ -341,6 +341,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
}
return noModifications
}
override fun after(range: RangeExpression, parent: Node): Iterable<IAstModification> {
val fromDt = range.from.inferType(program).getOr(DataType.UNDEFINED)
val toDt = range.to.inferType(program).getOr(DataType.UNDEFINED)
@ -365,6 +366,14 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
parent: Node
): List<IAstModification> {
if(varDt!=DataType.UNDEFINED) {
if(fromDt==varDt && toDt==varDt) {
return noModifications
} else if(fromDt==toDt && fromDt.isAssignableTo(varDt)) {
return noModifications
}
}
if(fromConst!=null) {
val smaller = NumericLiteral.optimalInteger(fromConst.number.toInt(), fromConst.position)
if(fromDt.largerThan(smaller.type)) {

View File

@ -237,4 +237,56 @@ main {
errors.errors.size shouldBe 1
errors.errors[0] shouldContain "name conflict"
}
test("various range datatype checks allow differences in type") {
val src="""
main {
sub func() -> ubyte {
cx16.r0++
return cx16.r0L
}
sub start() {
bool[256] @shared cells
word starw
byte bb
uword uw
ubyte ub
starw = (240-64 as word) + func()
for starw in 50 downto 10 {
cx16.r0++
}
for starw in cx16.r0L downto 10 {
cx16.r0++
}
for ub in 0 to len(cells)-1 {
cx16.r0++
}
for ub in cx16.r0L to len(cells)-1 {
cx16.r0++
}
for bb in 50 downto 10 {
cx16.r0++
}
for bb in cx16.r0sL downto 10 {
cx16.r0++
}
for starw in 500 downto 10 {
cx16.r0++
}
for uw in 50 downto 10 {
cx16.r0++
}
for uw in 500 downto 10 {
cx16.r0++
}
}
}"""
compileText(C64Target(), false, src, writeAssembly = false) shouldNotBe null
compileText(C64Target(), true, src, writeAssembly = false) shouldNotBe null
}
})

View File

@ -1,8 +1,6 @@
TODO
====
word starw; for starw in 50 downto 0 -> compiler error word loop variable can only loop over bytes or words FIX in adjustRangeDts() most likely
Regenerate skeleton doc files.
Improve register load order in subroutine call args assignments:

View File

@ -1,19 +1,25 @@
%import textio
%zeropage basicsafe
%option no_sysinit
main {
sub func() -> ubyte {
cx16.r0++
return cx16.r0L
}
sub start() {
bool[256] cells
bool[256] @shared cells
word starw
byte bb
uword uw
ubyte ub
for starw in 50 downto 10 { ; TODO fix compiler error + add unit test for this
starw = (240-64 as word) + func()
for starw in 50 downto 10 {
cx16.r0++
}
for starw in cx16.r0L downto 10 { ; TODO fix compiler error + add unit test for this
for starw in cx16.r0L downto 10 {
cx16.r0++
}
@ -30,16 +36,15 @@ main {
cx16.r0++
}
; for starw in 500 downto 10 {
; cx16.r0++
; }
; for uw in 50 downto 10 {
; cx16.r0++
; }
; for uw in 500 downto 10 {
; cx16.r0++
; }
for starw in 500 downto 10 {
cx16.r0++
}
for uw in 50 downto 10 {
cx16.r0++
}
for uw in 500 downto 10 {
cx16.r0++
}
}
}