diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 416269692..10512a06c 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -3,6 +3,7 @@ package prog8.compiler.astprocessing import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.NumericDatatypes +import prog8.ast.base.SyntaxError import prog8.ast.base.VarDeclType import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.NumericLiteralValue @@ -21,19 +22,31 @@ class AstPreprocessor(val program: Program) : AstWalker() { // has to be done before the constant folding, otherwise certain checks there will fail on invalid range sizes val modifications = mutableListOf() if(range.from !is NumericLiteralValue) { - val constval = range.from.constValue(program) - if(constval!=null) - modifications += IAstModification.ReplaceNode(range.from, constval, range) + try { + val constval = range.from.constValue(program) + if (constval != null) + modifications += IAstModification.ReplaceNode(range.from, constval, range) + } catch (x: SyntaxError) { + // syntax errors will be reported later + } } if(range.to !is NumericLiteralValue) { - val constval = range.to.constValue(program) - if(constval!=null) - modifications += IAstModification.ReplaceNode(range.to, constval, range) + try { + val constval = range.to.constValue(program) + if(constval!=null) + modifications += IAstModification.ReplaceNode(range.to, constval, range) + } catch (x: SyntaxError) { + // syntax errors will be reported later + } } if(range.step !is NumericLiteralValue) { - val constval = range.step.constValue(program) - if(constval!=null) - modifications += IAstModification.ReplaceNode(range.step, constval, range) + try { + val constval = range.step.constValue(program) + if(constval!=null) + modifications += IAstModification.ReplaceNode(range.step, constval, range) + } catch (x: SyntaxError) { + // syntax errors will be reported later + } } return modifications } diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index 83585abfd..5bc2e3dfa 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -4,11 +4,13 @@ import io.kotest.assertions.withClue import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.types.instanceOf import prog8.ast.base.DataType import prog8.ast.base.Position import prog8.ast.expressions.* import prog8.ast.statements.ForLoop import prog8.ast.statements.VarDecl +import prog8.compiler.printProgram import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target import prog8.compilerinterface.size @@ -262,4 +264,42 @@ class TestCompilerOnRanges: FunSpec({ expr.size() shouldBe 6 expr.toConstantIntegerRange() } + + test("range with negative step should be constvalue") { + val result = compileText(C64Target, false, """ + main { + sub start() { + ubyte[] array = 100 to 50 step -2 + ubyte xx + for xx in 100 to 50 step -2 { + } + } + } + """).assertSuccess() + val statements = result.program.entrypoint.statements + val array = (statements[0] as VarDecl).value + array shouldBe instanceOf() + (array as ArrayLiteralValue).value.size shouldBe 26 + val forloop = (statements.dropLast(1).last() as ForLoop) + forloop.iterable shouldBe instanceOf() + (forloop.iterable as RangeExpr).step shouldBe NumericLiteralValue(DataType.UBYTE, -2.0, Position.DUMMY) + } + + test("range with start/end variables should be ok") { + val result = compileText(C64Target, false, """ + main { + sub start() { + byte from = 100 + byte end = 50 + byte xx + for xx in from to end step -2 { + } + } + } + """).assertSuccess() + val statements = result.program.entrypoint.statements + val forloop = (statements.dropLast(1).last() as ForLoop) + forloop.iterable shouldBe instanceOf() + (forloop.iterable as RangeExpr).step shouldBe NumericLiteralValue(DataType.UBYTE, -2.0, Position.DUMMY) + } }) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 51b580f53..a601eacaf 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,10 +4,6 @@ TODO For next compiler release (7.4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -BUG: line-circle-text doesn't compile anymore due to missing symbol! - Add unit test to avoid this in the future? - - Use GoSub to call subroutines (statements): - [DONE] allow separate assigns to subroutine's parameter variables / registers - [DONE] turn a regular subroutine call into assignments to the parameters + GoSub (take code from gosub branch) diff --git a/examples/test.p8 b/examples/test.p8 index 9f8662379..e9222b96f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,24 +5,6 @@ main { sub start() { - test_stack.test() - - ubyte[20] xpos = 19 to 0 step -1 - ubyte[20] ypos = 19 to 0 step -1 - - ubyte ball - for ball in 0 to len(xpos)-1 { - ubyte xx = xpos[ball] + 1 - ubyte yy = ypos[ball] - txt.setchr(xx,yy,87) ; correct codegen - txt.setclr(xx,yy,5) ; correct codegen - txt.setchr(xpos[ball], ypos[ball], 81) ; TODO WRONG CODEGEN WITH NOOPT - txt.setclr(xpos[ball], ypos[ball], 6) ; TODO WRONG CODEGEN WITH NOOPT - } - - test_stack.test() - repeat { - } - + ubyte[] array = 100 to 50 step -2 } }