added compiler check against impossible for loop range (unsigned downto exactly 0 with non-const startvalue and step != -1)

This commit is contained in:
Irmen de Jong 2021-04-21 22:45:03 +02:00
parent ee1c43ca91
commit 4c080afb76
3 changed files with 73 additions and 9 deletions

View File

@ -92,6 +92,18 @@ internal class AstChecker(private val program: Program,
}
override fun visit(forLoop: ForLoop) {
fun checkUnsignedLoopDownto0(range: RangeExpr?) {
if(range==null)
return
val step = range.step.constValue(program)?.number?.toDouble() ?: 1.0
if(step < -1.0) {
val limit = range.to.constValue(program)?.number?.toDouble()
if(limit==0.0 && range.from.constValue(program)==null)
errors.err("for unsigned loop variable it's not possible to count down with step != -1 from a non-const value to exactly zero due to value wrapping", forLoop.position)
}
}
val iterableDt = forLoop.iterable.inferType(program).typeOrElse(DataType.BYTE)
if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpr) {
errors.err("can only loop over an iterable type", forLoop.position)
@ -104,11 +116,15 @@ internal class AstChecker(private val program: Program,
DataType.UBYTE -> {
if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt != DataType.STR)
errors.err("ubyte loop variable can only loop over unsigned bytes or strings", forLoop.position)
checkUnsignedLoopDownto0(forLoop.iterable as? RangeExpr)
}
DataType.UWORD -> {
if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.UWORD && iterableDt != DataType.STR &&
iterableDt != DataType.ARRAY_UB && iterableDt!= DataType.ARRAY_UW)
errors.err("uword loop variable can only loop over unsigned bytes, words or strings", forLoop.position)
checkUnsignedLoopDownto0(forLoop.iterable as? RangeExpr)
}
DataType.BYTE -> {
if(iterableDt!= DataType.BYTE && iterableDt!= DataType.ARRAY_B)
@ -146,6 +162,7 @@ internal class AstChecker(private val program: Program,
super.visit(forLoop)
}
override fun visit(jump: Jump) {
val ident = jump.identifier
if(ident!=null) {

View File

@ -40,6 +40,13 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
val modifiedLabel2 = asmgen.makeLabel("for_modifiedb")
asmgen.loopEndLabels.push(endLabel)
val stepsize=range.step.constValue(program)!!.number.toInt()
if(stepsize < -1) {
val limit = range.to.constValue(program)?.number?.toDouble()
if(limit==0.0)
throw AssemblyError("for unsigned loop variable it's not possible to count down with step != -1 from a non-const value to exactly zero due to value wrapping")
}
when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> {
if (stepsize==1 || stepsize==-1) {

View File

@ -7,21 +7,61 @@
main {
sub start() {
ubyte num_entries
ubyte fromub = 120
uword fromuw = 400
byte fromb = 120
word fromw = 400
num_entries = 10
ubyte ix
for ix in (num_entries-1)*2 downto 0 step -2 {
txt.print_ub(ix)
uword counter
byte bc
ubyte ubc
word wc
uword uwc
counter = 0
for bc in fromb to 0 step -1 {
counter++
txt.print_b(bc)
txt.spc()
}
txt.nl()
num_entries = 10
for ix in num_entries-1 downto 0 {
txt.print_ub(ix*2)
txt.print_uw(counter)
txt.nl()
txt.nl()
counter = 0
for ubc in fromub to 0 step -1 {
counter++
txt.print_ub(ubc)
txt.spc()
}
txt.nl()
txt.print_uw(counter)
txt.nl()
txt.nl()
counter = 0
for wc in fromw to 0 step -1 {
counter++
txt.print_w(wc)
txt.spc()
}
txt.nl()
txt.print_uw(counter)
txt.nl()
txt.nl()
; TODO FIX THIS LOOP??
counter = 0
for uwc in fromuw to 0 step -1 {
counter++
txt.print_uw(uwc)
txt.spc()
}
txt.nl()
txt.print_uw(counter)
txt.nl()
txt.nl()
}
}