fix invalid range size check when stepval is not a positive integer

This commit is contained in:
Irmen de Jong 2021-11-29 02:01:19 +01:00
parent 4ac169b210
commit b438d8aec0
7 changed files with 47 additions and 7 deletions

View File

@ -146,7 +146,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
// convert the initializer range expression to an actual array // convert the initializer range expression to an actual array
val declArraySize = decl.arraysize?.constIndex() val declArraySize = decl.arraysize?.constIndex()
if(declArraySize!=null && declArraySize!=rangeExpr.size()) if(declArraySize!=null && declArraySize!=rangeExpr.size())
errors.err("range expression size doesn't match declared array size", decl.value?.position!!) errors.err("range expression size (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!)
val constRange = rangeExpr.toConstantIntegerRange() val constRange = rangeExpr.toConstantIntegerRange()
if(constRange!=null) { if(constRange!=null) {
val eltType = rangeExpr.inferType(program).getOr(DataType.UBYTE) val eltType = rangeExpr.inferType(program).getOr(DataType.UBYTE)

View File

@ -255,7 +255,7 @@ fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget
private fun processAst(program: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) { private fun processAst(program: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
// perform initial syntax checks and processings // perform initial syntax checks and processings
println("Processing for target ${compilerOptions.compTarget.name}...") println("Processing for target ${compilerOptions.compTarget.name}...")
program.preprocessAst() program.preprocessAst(program)
program.checkIdentifiers(errors, compilerOptions) program.checkIdentifiers(errors, compilerOptions)
errors.report() errors.report()
// TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR // TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR

View File

@ -65,8 +65,8 @@ internal fun Program.verifyFunctionArgTypes() {
fixer.visit(this) fixer.visit(this)
} }
internal fun Program.preprocessAst() { internal fun Program.preprocessAst(program: Program) {
val transforms = AstPreprocessor() val transforms = AstPreprocessor(program)
transforms.visit(this) transforms.visit(this)
var mods = transforms.applyModifications() var mods = transforms.applyModifications()
while(mods>0) while(mods>0)

View File

@ -1,9 +1,12 @@
package prog8.compiler.astprocessing package prog8.compiler.astprocessing
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.NumericDatatypes import prog8.ast.base.NumericDatatypes
import prog8.ast.base.VarDeclType import prog8.ast.base.VarDeclType
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.RangeExpr
import prog8.ast.statements.AnonymousScope import prog8.ast.statements.AnonymousScope
import prog8.ast.statements.AssignTarget import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Assignment import prog8.ast.statements.Assignment
@ -12,7 +15,28 @@ import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
class AstPreprocessor : AstWalker() { class AstPreprocessor(val program: Program) : AstWalker() {
override fun after(range: RangeExpr, parent: Node): Iterable<IAstModification> {
// 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)
}
if(range.to !is NumericLiteralValue) {
val constval = range.to.constValue(program)
if(constval!=null)
modifications += IAstModification.ReplaceNode(range.to, constval, range)
}
if(range.step !is NumericLiteralValue) {
val constval = range.step.constValue(program)
if(constval!=null)
modifications += IAstModification.ReplaceNode(range.step, constval, range)
}
return modifications
}
override fun before(scope: AnonymousScope, parent: Node): Iterable<IAstModification> { override fun before(scope: AnonymousScope, parent: Node): Iterable<IAstModification> {

View File

@ -69,11 +69,12 @@ fun RangeExpr.toConstantIntegerRange(): IntProgression? {
val fromLv = from as? NumericLiteralValue val fromLv = from as? NumericLiteralValue
val toLv = to as? NumericLiteralValue val toLv = to as? NumericLiteralValue
if(fromLv==null || toLv==null) val stepLv = step as? NumericLiteralValue
if(fromLv==null || toLv==null || stepLv==null)
return null return null
val fromVal = fromLv.number.toInt() val fromVal = fromLv.number.toInt()
val toVal = toLv.number.toInt() val toVal = toLv.number.toInt()
val stepVal = (step as? NumericLiteralValue)?.number?.toInt() ?: 1 val stepVal = stepLv.number.toInt()
return makeRange(fromVal, toVal, stepVal) return makeRange(fromVal, toVal, stepVal)
} }

View File

@ -5,6 +5,10 @@ For next compiler release (7.4)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BUG: balls example crashes / animates wrong! BUG: balls example crashes / animates wrong!
caused by c83882161521378f20dc0076c01e18e8556e363e 'refactor function arguments codegen a bit'
on the lines that call txt.setclr(BX[lp], BY[lp], BC[lp]) - they work with regular vars as args
so, something wrong with clobber/arg order when passing array lookups??
Add unit test to avoid this in the future?
Use GoSub to call subroutines (statements): Use GoSub to call subroutines (statements):

View File

@ -6,6 +6,17 @@ main {
sub start() { sub start() {
test_stack.test() test_stack.test()
ubyte[50] xpos = 49 to 0 step -1
ubyte[50] ypos = 49 to 0 step -1
ubyte ball
for ball in 0 to len(xpos)-1 {
txt.print_ub(xpos[ball])
txt.spc()
txt.print_ub(ypos[ball])
txt.nl()
}
ubyte @shared x1 = 10 ubyte @shared x1 = 10
ubyte @shared x2 = 20 ubyte @shared x2 = 20
ubyte @shared x3 = 30 ubyte @shared x3 = 30