diff --git a/compiler/res/version.txt b/compiler/res/version.txt index 752a72c42..2ec85ad14 100644 --- a/compiler/res/version.txt +++ b/compiler/res/version.txt @@ -1,2 +1,2 @@ -1.61 +1.62 diff --git a/compiler/src/prog8/optimizer/ConstantFolding.kt b/compiler/src/prog8/optimizer/ConstantFolding.kt index b9df18325..09a843c1a 100644 --- a/compiler/src/prog8/optimizer/ConstantFolding.kt +++ b/compiler/src/prog8/optimizer/ConstantFolding.kt @@ -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 { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b424bfc98..5cf48c9c7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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 diff --git a/examples/test.p8 b/examples/test.p8 index 8c1f68767..efd13a2d5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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: ") diff --git a/examples/testforloops.p8 b/examples/testforloops.p8 index 841cb7e4c..8bf9b7831 100644 --- a/examples/testforloops.p8 +++ b/examples/testforloops.p8 @@ -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