fix syntaxerror in const processing of ranges if it contained variables

This commit is contained in:
Irmen de Jong 2021-11-29 23:36:41 +01:00
parent 7748c261da
commit 9ecf95b075
4 changed files with 63 additions and 32 deletions

View File

@ -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<IAstModification>()
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
}

View File

@ -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<ArrayLiteralValue>()
(array as ArrayLiteralValue).value.size shouldBe 26
val forloop = (statements.dropLast(1).last() as ForLoop)
forloop.iterable shouldBe instanceOf<RangeExpr>()
(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<RangeExpr>()
(forloop.iterable as RangeExpr).step shouldBe NumericLiteralValue(DataType.UBYTE, -2.0, Position.DUMMY)
}
})

View File

@ -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)

View File

@ -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
}
}