mirror of
https://github.com/irmen/prog8.git
synced 2024-10-18 16:24:26 +00:00
various for loops
This commit is contained in:
parent
50aa286d3a
commit
299ea72d70
@ -119,10 +119,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
checkResult.add(ExpressionError("can only loop over an iterable type", forLoop.position))
|
checkResult.add(ExpressionError("can only loop over an iterable type", forLoop.position))
|
||||||
} else {
|
} else {
|
||||||
if (forLoop.loopRegister != null) {
|
if (forLoop.loopRegister != null) {
|
||||||
printWarning("using a register as loop variable is risky (it could get clobbered)", forLoop.position)
|
|
||||||
// loop register
|
// loop register
|
||||||
if (iterableDt != DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt !in StringDatatypes)
|
if (iterableDt != DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt !in StringDatatypes)
|
||||||
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
|
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
|
||||||
|
if(forLoop.loopRegister!=Register.A)
|
||||||
|
checkResult.add(ExpressionError("it's only possible to use A as a loop register", forLoop.position))
|
||||||
} else {
|
} else {
|
||||||
// loop variable
|
// loop variable
|
||||||
val loopvar = forLoop.loopVar!!.targetVarDecl(program.namespace)
|
val loopvar = forLoop.loopVar!!.targetVarDecl(program.namespace)
|
||||||
|
@ -339,9 +339,9 @@ internal class AsmGen2(val program: Program,
|
|||||||
.filter {it.datatype in StringDatatypes }
|
.filter {it.datatype in StringDatatypes }
|
||||||
.map { it to encodeStr((it.value as ReferenceLiteralValue).str!!, it.datatype) }
|
.map { it to encodeStr((it.value as ReferenceLiteralValue).str!!, it.datatype) }
|
||||||
.groupBy({it.second}, {it.first})
|
.groupBy({it.second}, {it.first})
|
||||||
for((encoded, vars) in encodedstringVars) {
|
for((encoded, variables) in encodedstringVars) {
|
||||||
vars.dropLast(1).forEach { out(it.name) }
|
variables.dropLast(1).forEach { out(it.name) }
|
||||||
val lastvar = vars.last()
|
val lastvar = variables.last()
|
||||||
outputStringvar(lastvar, encoded)
|
outputStringvar(lastvar, encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,35 +953,178 @@ internal class AsmGen2(val program: Program,
|
|||||||
|
|
||||||
private fun translate(stmt: ForLoop) {
|
private fun translate(stmt: ForLoop) {
|
||||||
val iterableDt = stmt.iterable.inferType(program)
|
val iterableDt = stmt.iterable.inferType(program)
|
||||||
|
val loopLabel = makeLabel("for_loop")
|
||||||
|
val endLabel = makeLabel("for_end")
|
||||||
when(stmt.iterable) {
|
when(stmt.iterable) {
|
||||||
is RangeExpr -> {
|
is RangeExpr -> {
|
||||||
|
val range = (stmt.iterable as RangeExpr).toConstantIntegerRange()
|
||||||
|
if(range==null)
|
||||||
|
TODO("non-const range loop")
|
||||||
|
if(range.isEmpty())
|
||||||
|
throw AssemblyError("empty range")
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
in ByteDatatypes -> {
|
in ByteDatatypes -> {
|
||||||
println("forloop over byte range $stmt") // TODO
|
if(stmt.loopRegister!=null) {
|
||||||
|
// loop register
|
||||||
|
if(stmt.loopRegister!=Register.A)
|
||||||
|
throw AssemblyError("can only use A")
|
||||||
|
when {
|
||||||
|
range.step==1 -> {
|
||||||
|
val counterLabel = makeLabel("for_counter")
|
||||||
|
out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $loopLabel+1
|
||||||
|
lda #${range.last-range.first+1 and 255}
|
||||||
|
sta $counterLabel
|
||||||
|
$loopLabel lda #0 ; modified""")
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
dec $counterLabel
|
||||||
|
beq $endLabel
|
||||||
|
inc $loopLabel+1
|
||||||
|
jmp $loopLabel
|
||||||
|
$counterLabel .byte 0
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
range.step==-1 -> {
|
||||||
|
val counterLabel = makeLabel("for_counter")
|
||||||
|
out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $loopLabel+1
|
||||||
|
lda #${range.first-range.last+1 and 255}
|
||||||
|
sta $counterLabel
|
||||||
|
$loopLabel lda #0 ; modified """)
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
dec $counterLabel
|
||||||
|
beq $endLabel
|
||||||
|
dec $loopLabel+1
|
||||||
|
jmp $loopLabel
|
||||||
|
$counterLabel .byte 0
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
range.step>0 -> {
|
||||||
|
val counterLabel = makeLabel("for_counter")
|
||||||
|
out("""
|
||||||
|
lda #${(range.last-range.first) / range.step + 1}
|
||||||
|
sta $counterLabel
|
||||||
|
lda #${range.first}
|
||||||
|
$loopLabel pha""")
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
pla
|
||||||
|
dec $counterLabel
|
||||||
|
beq $endLabel
|
||||||
|
clc
|
||||||
|
adc #${range.step}
|
||||||
|
jmp $loopLabel
|
||||||
|
$counterLabel .byte 0
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val counterLabel = makeLabel("for_counter")
|
||||||
|
out("""
|
||||||
|
lda #${(range.first-range.last) / range.step.absoluteValue + 1}
|
||||||
|
sta $counterLabel
|
||||||
|
lda #${range.first}
|
||||||
|
$loopLabel pha""")
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
pla
|
||||||
|
dec $counterLabel
|
||||||
|
beq $endLabel
|
||||||
|
sec
|
||||||
|
sbc #${range.step.absoluteValue}
|
||||||
|
jmp $loopLabel
|
||||||
|
$counterLabel .byte 0
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TODO("loop over byte range via loopvar $stmt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
println("forloop over word range $stmt") // TODO
|
TODO("forloop over word range $stmt") // TODO
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
else -> throw AssemblyError("range expression can only be byte or word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
val decl = (stmt.iterable as IdentifierReference).targetVarDecl(program.namespace)!!
|
val ident = (stmt.iterable as IdentifierReference)
|
||||||
|
val iterableName = asmIdentifierName(ident)
|
||||||
|
val decl = ident.targetVarDecl(program.namespace)!!
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
DataType.STR, DataType.STR_S -> {
|
DataType.STR, DataType.STR_S -> {
|
||||||
println("forloop over string $stmt") // TODO (ends at 0 byte)
|
if(stmt.loopRegister!=null) {
|
||||||
|
// loop register
|
||||||
|
if(stmt.loopRegister!=Register.A)
|
||||||
|
throw AssemblyError("can only use A")
|
||||||
|
out("""
|
||||||
|
lda #<$iterableName
|
||||||
|
ldy #>$iterableName
|
||||||
|
sta $loopLabel+1
|
||||||
|
sty $loopLabel+2
|
||||||
|
$loopLabel lda ${65535.toHex()} ; modified
|
||||||
|
beq $endLabel""")
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
inc $loopLabel+1
|
||||||
|
bne $loopLabel
|
||||||
|
inc $loopLabel+2
|
||||||
|
bne $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
} else {
|
||||||
|
TODO("loop over string via loopvar $stmt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||||
val size = decl.arraysize!!.size()
|
val length = decl.arraysize!!.size()
|
||||||
println("forloop over byte array of len $size $stmt") // TODO (ends at length of array)
|
if(stmt.loopRegister!=null) {
|
||||||
|
// loop register
|
||||||
|
if(stmt.loopRegister!=Register.A)
|
||||||
|
throw AssemblyError("can only use A")
|
||||||
|
val counterLabel = makeLabel("for_counter")
|
||||||
|
val modifiedLabel = makeLabel("for_modified")
|
||||||
|
out("""
|
||||||
|
lda #<$iterableName
|
||||||
|
ldy #>$iterableName
|
||||||
|
sta $modifiedLabel+1
|
||||||
|
sty $modifiedLabel+2
|
||||||
|
ldy #0
|
||||||
|
$loopLabel sty $counterLabel
|
||||||
|
cpy #$length
|
||||||
|
beq $endLabel
|
||||||
|
$modifiedLabel lda ${65535.toHex()},y ; modified
|
||||||
|
""")
|
||||||
|
translate(stmt.body)
|
||||||
|
out("""
|
||||||
|
ldy $counterLabel
|
||||||
|
iny
|
||||||
|
jmp $loopLabel
|
||||||
|
$counterLabel .byte 0
|
||||||
|
$endLabel""")
|
||||||
|
} else {
|
||||||
|
TODO("loop variable over bytearray of len $length")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||||
val size = decl.arraysize!!.size()
|
val length = decl.arraysize!!.size()
|
||||||
println("forloop over word array len $size $stmt") // TODO
|
println("forloop over word array len $length $stmt") // TODO
|
||||||
|
if(stmt.loopRegister!=null) {
|
||||||
|
TODO("loop register over wordarray of len $length")
|
||||||
|
} else {
|
||||||
|
TODO("loop variable over wordarray of len $length")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_F -> {
|
DataType.ARRAY_F -> {
|
||||||
val size = decl.arraysize!!.size()
|
val length = decl.arraysize!!.size()
|
||||||
println("forloop over float array len $size $stmt") // TODO
|
println("forloop over float array len $length $stmt") // TODO
|
||||||
|
if(stmt.loopRegister!=null) {
|
||||||
|
throw AssemblyError("can't use register to loop over floats")
|
||||||
|
} else {
|
||||||
|
TODO("loop variable over floatarray of len $length")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("can't iterate over $iterableDt")
|
else -> throw AssemblyError("can't iterate over $iterableDt")
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,30 @@ main {
|
|||||||
c64.CHROUT(',')
|
c64.CHROUT(',')
|
||||||
}
|
}
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
;
|
|
||||||
; for A in 10 to 20 {
|
for A in 10 to 20 {
|
||||||
; c64scr.print_ub(A)
|
c64scr.print_ub(A)
|
||||||
; c64.CHROUT(',')
|
c64.CHROUT(',')
|
||||||
; }
|
}
|
||||||
; c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for A in 20 to 10 step -1 {
|
||||||
|
c64scr.print_ub(A)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for A in 10 to 21 step 3 {
|
||||||
|
c64scr.print_ub(A)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for A in 24 to 10 step -3 {
|
||||||
|
c64scr.print_ub(A)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
; for var2 in 10 to 20 {
|
; for var2 in 10 to 20 {
|
||||||
; c64scr.print_ub(var2)
|
; c64scr.print_ub(var2)
|
||||||
|
Loading…
Reference in New Issue
Block a user