fixed some type cast compiler errors in for loops

This commit is contained in:
Irmen de Jong 2019-08-26 23:38:59 +02:00
parent 9afe451b8d
commit 772e48105e
5 changed files with 66 additions and 58 deletions

View File

@ -1,2 +1,2 @@
1.61
1.62

View File

@ -562,49 +562,79 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
} catch (x: ExpressionError) {
return range
}
val newStep: Expression = stepLiteral?.cast(targetDt) ?: range.step
val newStep: Expression = try {
stepLiteral?.cast(targetDt)?: range.step
} catch(ee: ExpressionError) {
range.step
}
return RangeExpr(newFrom, newTo, newStep, range.position)
}
val forLoop2 = super.visit(forLoop) as ForLoop
// check if we need to adjust an array literal to the loop variable's datatype
val array = forLoop2.iterable as? ArrayLiteralValue
if(array!=null) {
val loopvarDt: DataType = when {
forLoop.loopVar!=null -> forLoop.loopVar!!.inferType(program).typeOrElse(DataType.UBYTE)
forLoop.loopRegister!=null -> DataType.UBYTE
else -> throw FatalAstException("weird for loop")
}
val arrayType = when(loopvarDt) {
DataType.UBYTE -> DataType.ARRAY_UB
DataType.BYTE -> DataType.ARRAY_B
DataType.UWORD -> DataType.ARRAY_UW
DataType.WORD -> DataType.ARRAY_W
DataType.FLOAT -> DataType.ARRAY_F
else -> throw FatalAstException("invalid array elt type")
}
val array2 = array.cast(arrayType)
if(array2!=null && array2!==array) {
forLoop2.iterable = array2
array2.linkParents(forLoop2)
array2.addToHeap()
}
}
// adjust the datatype of a range expression in for loops to the loop variable.
val resultStmt = super.visit(forLoop) as ForLoop
val iterableRange = resultStmt.iterable as? RangeExpr ?: return resultStmt
val iterableRange = forLoop2.iterable as? RangeExpr ?: return forLoop2
val rangeFrom = iterableRange.from as? NumericLiteralValue
val rangeTo = iterableRange.to as? NumericLiteralValue
if(rangeFrom==null || rangeTo==null) return resultStmt
if(rangeFrom==null || rangeTo==null) return forLoop2
val loopvar = resultStmt.loopVar?.targetVarDecl(program.namespace)
val loopvar = forLoop2.loopVar?.targetVarDecl(program.namespace)
if(loopvar!=null) {
val stepLiteral = iterableRange.step as? NumericLiteralValue
when(loopvar.datatype) {
DataType.UBYTE -> {
if(rangeFrom.type!= DataType.UBYTE) {
// attempt to translate the iterable into ubyte values
resultStmt.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
forLoop2.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
}
}
DataType.BYTE -> {
if(rangeFrom.type!= DataType.BYTE) {
// attempt to translate the iterable into byte values
resultStmt.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
forLoop2.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
}
}
DataType.UWORD -> {
if(rangeFrom.type!= DataType.UWORD) {
// attempt to translate the iterable into uword values
resultStmt.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
forLoop2.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
}
}
DataType.WORD -> {
if(rangeFrom.type!= DataType.WORD) {
// attempt to translate the iterable into word values
resultStmt.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
forLoop2.iterable = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange)
}
}
else -> throw FatalAstException("invalid loopvar datatype $loopvar")
}
}
return resultStmt
return forLoop2
}
override fun visit(arrayLiteral: ArrayLiteralValue): Expression {

View File

@ -46,11 +46,7 @@ without having to to index into the stack?
Bugs
^^^^
There are a few erroneous compiler errors when dealing with certain for loops::
for bb in [1,2,3] ; byte loop variable can only loop over bytes
for ww in [1111,3333,555,999] ; word loop variable can only loop over bytes or words
for uw in 20 to 10 step -1 ; 'can't cast BYTE into UWORD'
Ofcourse there are still bugs to fix ;)
Misc

View File

@ -1,10 +1,5 @@
%zeropage basicsafe
; TODO fix compiler errors:
; for bb in [1,2,3] -> byte loop variable can only loop over bytes
; for ww in [1111,3333,555,999] -> word loop variable can only loop over bytes or words
; for uw in 20 to 10 step -1 -> 'can't cast BYTE into UWORD'
main {
sub start() {
@ -12,21 +7,16 @@ main {
byte[] barr = [22,-33,-44,55,66]
ubyte endub1
byte endb1
uword count
ubyte aa
ubyte ub
byte bb
uword uw
word total
uword count
for count in 10 to 20 step 1 {
}
for count in 20 to 10 step -1 { ; @todo fix compiler error
}
; ---------- BYTE var ---------
; @todo fix byte loop in arrayliteral 'Error: byte loop variable can only loop over bytes'
count = 0
total = 0
c64scr.print("byte var in arrayliteral: ")
@ -46,7 +36,6 @@ main {
word endw1
word ww
; @todo fix compiler error
count = 0
total = 0
c64scr.print("word var in arrayliteral: ")

View File

@ -1,10 +1,5 @@
%zeropage basicsafe
; TODO fix compiler errors:
; for bb in [1,2,3] -> byte loop variable can only loop over bytes
; for ww in [1111,3333,555,999] -> word loop variable can only loop over bytes or words
; for uw in 20 to 10 step -1 -> 'can't cast BYTE into UWORD'
main {
sub start() {
@ -416,18 +411,17 @@ main {
; ---------- BYTE var ---------
; @todo fix byte loop in arrayliteral 'Error: byte loop variable can only loop over bytes'
; count = 0
; total = 0
; c64scr.print("byte var in arrayliteral: ")
; for bb in [1,3,5,99] {
; count++
; total += bb
; }
; if count==4 and total==108
; c64scr.print("ok\n")
; else
; c64scr.print("fail!!!\n")
count = 0
total = 0
c64scr.print("byte var in arrayliteral: ")
for bb in [1,3,5,99] {
count++
total += bb
}
if count==4 and total==108
c64scr.print("ok\n")
else
c64scr.print("fail!!!\n")
count = 0
total = 0
@ -793,18 +787,17 @@ main {
word endw1
word ww
; @todo fix compiler error
; count = 0
; total = 0
; c64scr.print("word var in arrayliteral: ")
; for ww in [1111,3333,555,999] {
; count++
; total += ww
; }
; if count==4 and total==5998
; c64scr.print("ok\n")
; else
; c64scr.print("fail!!!\n")
count = 0
total = 0
c64scr.print("word var in arrayliteral: ")
for ww in [1111,3333,555,999] {
count++
total += ww
}
if count==4 and total==5998
c64scr.print("ok\n")
else
c64scr.print("fail!!!\n")
count = 0
total = 0