mirror of
https://github.com/irmen/prog8.git
synced 2024-12-22 18:30:01 +00:00
add error message for invalid step size in range expression
This commit is contained in:
parent
ecbcc277b8
commit
3e6d16a7a8
@ -589,22 +589,21 @@ class IRCodeGen(
|
|||||||
val iterable = forLoop.iterable as PtRange
|
val iterable = forLoop.iterable as PtRange
|
||||||
val step = iterable.step.number.toInt()
|
val step = iterable.step.number.toInt()
|
||||||
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
||||||
val rangeEndUntyped = (iterable.to as PtNumber).number.toInt() + step
|
val rangeEndExclusiveUntyped = (iterable.to as PtNumber).number.toInt() + step
|
||||||
if(step==0)
|
if(step==0)
|
||||||
throw AssemblyError("step 0")
|
throw AssemblyError("step 0")
|
||||||
if(step>0 && rangeEndUntyped<rangeStart || step<0 && rangeEndUntyped>rangeStart)
|
if(step>0 && rangeEndExclusiveUntyped<rangeStart || step<0 && rangeEndExclusiveUntyped>rangeStart)
|
||||||
throw AssemblyError("empty range")
|
throw AssemblyError("empty range")
|
||||||
val rangeEndWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndUntyped and 255 else rangeEndUntyped and 65535
|
val rangeEndExclusiveWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndExclusiveUntyped and 255 else rangeEndExclusiveUntyped and 65535
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val chunk = IRCodeChunk(null, null)
|
val chunk = IRCodeChunk(null, null)
|
||||||
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1=indexReg, immediate = rangeStart)
|
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1=indexReg, immediate = rangeStart)
|
||||||
chunk += IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol)
|
chunk += IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||||
result += chunk
|
result += chunk
|
||||||
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
||||||
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step)
|
val chunk2 = addConstMem(loopvarDtIr, null, loopvarSymbol, step)
|
||||||
val chunk2 = IRCodeChunk(null, null)
|
|
||||||
chunk2 += IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
chunk2 += IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||||
chunk2 += IRInstruction(Opcode.BNE, loopvarDtIr, reg1 = indexReg, immediate = rangeEndWrapped, labelSymbol = loopLabel)
|
chunk2 += IRInstruction(Opcode.BNE, loopvarDtIr, reg1 = indexReg, immediate = rangeEndExclusiveWrapped, labelSymbol = loopLabel)
|
||||||
result += chunk2
|
result += chunk2
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -280,10 +280,16 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||||||
val rangeExpr = decl.value as? RangeExpression
|
val rangeExpr = decl.value as? RangeExpression
|
||||||
if(rangeExpr!=null) {
|
if(rangeExpr!=null) {
|
||||||
// convert the initializer range expression to an actual array
|
// convert the initializer range expression to an actual array
|
||||||
|
val constRange = rangeExpr.toConstantIntegerRange()
|
||||||
|
if(constRange?.isEmpty()==true) {
|
||||||
|
if(constRange.first>constRange.last && constRange.step>=0)
|
||||||
|
errors.err("descending range with positive step", decl.value?.position!!)
|
||||||
|
else if(constRange.first<constRange.last && constRange.step<=0)
|
||||||
|
errors.err("ascending range with negative step", decl.value?.position!!)
|
||||||
|
}
|
||||||
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 (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!)
|
errors.err("range expression size (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!)
|
||||||
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)
|
||||||
val newValue = if(eltType in ByteDatatypes) {
|
val newValue = if(eltType in ByteDatatypes) {
|
||||||
|
@ -264,7 +264,15 @@ class TestCompilerOnRanges: FunSpec({
|
|||||||
NumericLiteral.optimalInteger(2, Position.DUMMY),
|
NumericLiteral.optimalInteger(2, Position.DUMMY),
|
||||||
Position.DUMMY)
|
Position.DUMMY)
|
||||||
expr.size() shouldBe 6
|
expr.size() shouldBe 6
|
||||||
expr.toConstantIntegerRange()
|
expr.toConstantIntegerRange() shouldBe (10..20 step 2)
|
||||||
|
|
||||||
|
val expr2 = RangeExpression(
|
||||||
|
NumericLiteral.optimalInteger(20, Position.DUMMY),
|
||||||
|
NumericLiteral.optimalInteger(10, Position.DUMMY),
|
||||||
|
NumericLiteral.optimalInteger(-3, Position.DUMMY),
|
||||||
|
Position.DUMMY)
|
||||||
|
expr2.size() shouldBe 4
|
||||||
|
expr2.toConstantIntegerRange() shouldBe (20 downTo 10 step 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("range with negative step should be constvalue") {
|
test("range with negative step should be constvalue") {
|
||||||
|
@ -3,11 +3,31 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start () {
|
sub start () {
|
||||||
ubyte[4] array = 10 to 13
|
ubyte[4] @shared array = 10 to 20 step 3
|
||||||
ubyte[4] array2 = 10 to 20 step 3
|
ubyte[4] @shared array2 = 20 downto 10 step -3
|
||||||
ubyte[4] array3 = 20 downto 10 step 3 ; TODO fix error about empty range expression
|
byte[7] @shared array3 = 10 downto -10 step -3
|
||||||
|
|
||||||
ubyte xx
|
ubyte xx
|
||||||
|
byte bb
|
||||||
|
|
||||||
|
for xx in array {
|
||||||
|
txt.print_ub(xx)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
for xx in array2 {
|
||||||
|
txt.print_ub(xx)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
for bb in array3 {
|
||||||
|
txt.print_b(bb)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
|
||||||
for xx in 10 to 20 step 3 { ; TODO fix IR/VM code that wraps around instead of stopping at 19
|
for xx in 10 to 20 step 3 { ; TODO fix IR/VM code that wraps around instead of stopping at 19
|
||||||
txt.print_ub(xx)
|
txt.print_ub(xx)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
@ -20,10 +40,31 @@ main {
|
|||||||
}
|
}
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
byte bb
|
|
||||||
for bb in 10 downto -10 step -3 { ; TODO fix IR/VM code that wraps around instead of stopping at -8
|
for bb in 10 downto -10 step -3 { ; TODO fix IR/VM code that wraps around instead of stopping at -8
|
||||||
txt.print_b(bb)
|
txt.print_b(bb)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txt.nl()
|
||||||
|
txt.nl()
|
||||||
|
ubyte ending = 20
|
||||||
|
|
||||||
|
for xx in 10 to ending step 3 {
|
||||||
|
txt.print_ub(xx)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
ending =10
|
||||||
|
for xx in 20 downto ending step -3 {
|
||||||
|
txt.print_ub(xx)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
byte endingb = -10
|
||||||
|
for bb in 10 downto endingb step -3 {
|
||||||
|
txt.print_b(bb)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user