From a18de75da962bfa0e36697177eb8c4444625ff6c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 29 Aug 2020 01:44:20 +0200 Subject: [PATCH] fix compiler loop and missing type checks on for loop range values --- .../src/prog8/ast/processing/AstChecker.kt | 21 ++++++++++++ .../optimizer/ConstantFoldingOptimizer.kt | 16 +++++---- examples/cx16/graphics.p8 | 34 ++++++++++++------- examples/test.p8 | 11 ++++++ 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index c0fa32a61..61c0ee97a 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -118,6 +118,11 @@ internal class AstChecker(private val program: Program, if(loopvar==null || loopvar.type== VarDeclType.CONST) { errors.err("for loop requires a variable to loop with", forLoop.position) } else { + + fun checkLoopRangeValues() { + + } + when (loopvar.datatype) { DataType.UBYTE -> { if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt != DataType.STR) @@ -142,6 +147,22 @@ internal class AstChecker(private val program: Program, } else -> errors.err("loop variable must be numeric type", forLoop.position) } + if(errors.isEmpty()) { + // check loop range values + val range = forLoop.iterable as? RangeExpr + if(range!=null) { + val from = range.from as? NumericLiteralValue + val to = range.to as? NumericLiteralValue + if(from != null) + checkValueTypeAndRange(loopvar.datatype, from) + else if(!range.from.inferType(program).istype(loopvar.datatype)) + errors.err("range start value is incompatible with loop variable type", range.position) + if(to != null) + checkValueTypeAndRange(loopvar.datatype, to) + else if(!range.to.inferType(program).istype(loopvar.datatype)) + errors.err("range end value is incompatible with loop variable type", range.position) + } + } } } diff --git a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt index da478dfd7..6204ae5b3 100644 --- a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -318,11 +318,11 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke } override fun after(forLoop: ForLoop, parent: Node): Iterable { - fun adjustRangeDt(rangeFrom: NumericLiteralValue, targetDt: DataType, rangeTo: NumericLiteralValue, stepLiteral: NumericLiteralValue?, range: RangeExpr): RangeExpr { + fun adjustRangeDt(rangeFrom: NumericLiteralValue, targetDt: DataType, rangeTo: NumericLiteralValue, stepLiteral: NumericLiteralValue?, range: RangeExpr): RangeExpr? { val fromCast = rangeFrom.cast(targetDt) val toCast = rangeTo.cast(targetDt) if(!fromCast.isValid || !toCast.isValid) - return range + return null val newStep = if(stepLiteral!=null) { @@ -351,28 +351,32 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke if(rangeFrom.type!= DataType.UBYTE) { // attempt to translate the iterable into ubyte values val newIter = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange) - return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) + if(newIter!=null) + return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) } } DataType.BYTE -> { if(rangeFrom.type!= DataType.BYTE) { // attempt to translate the iterable into byte values val newIter = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange) - return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) + if(newIter!=null) + return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) } } DataType.UWORD -> { if(rangeFrom.type!= DataType.UWORD) { // attempt to translate the iterable into uword values val newIter = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange) - return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) + if(newIter!=null) + return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) } } DataType.WORD -> { if(rangeFrom.type!= DataType.WORD) { // attempt to translate the iterable into word values val newIter = adjustRangeDt(rangeFrom, loopvar.datatype, rangeTo, stepLiteral, iterableRange) - return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) + if(newIter!=null) + return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop)) } } else -> throw FatalAstException("invalid loopvar datatype $loopvar") diff --git a/examples/cx16/graphics.p8 b/examples/cx16/graphics.p8 index 9681c501a..293f02088 100644 --- a/examples/cx16/graphics.p8 +++ b/examples/cx16/graphics.p8 @@ -9,22 +9,32 @@ main { cx16.screen_set_mode($80) cx16.r0=0 - cx16.GRAPH_init() - cx16.GRAPH_set_colors(0, 0, 0) + cx16.FB_init() + cx16.r0 = 0 + cx16.r1 = 0 + cx16.FB_cursor_position() uword xx - for xx in 0 to 319 step 32 { - cx16.GRAPH_clear() - ubyte q - for q in 0 to 31 { - cx16.GRAPH_set_colors(q, 2, 0) - cx16.r0 = xx+q - cx16.r1=0 - cx16.r2=rnd() - cx16.r3=199 - cx16.GRAPH_draw_line() + ubyte yy + for yy in 199 downto 0 { + for xx in 319 downto 0 { ; TODO fix compiler hang -- should be error message when range is too large + cx16.FB_set_pixel( yy+lsb(xx)) } } + +; uword xx +; for xx in 0 to 319 step 32 { +; cx16.GRAPH_clear() +; ubyte q +; for q in 0 to 31 { +; cx16.GRAPH_set_colors(q, 2, 0) +; cx16.r0 = xx+q +; cx16.r1=0 +; cx16.r2=rnd() +; cx16.r3=199 +; cx16.GRAPH_draw_line() +; } +; } } } diff --git a/examples/test.p8 b/examples/test.p8 index b946f351b..ff4f38e85 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,6 +3,17 @@ main { sub start() { + + ubyte xx + ubyte yy + for yy in 199 downto 0 { + for xx in 255 downto 0 { + ; TODO also fix that the asm is invalid for word iterator variable. + } + } + + + byte b1 byte b2 byte b3