fixed missing initialization of loop index var

This commit is contained in:
Irmen de Jong 2018-12-29 17:02:48 +01:00
parent 9ddda9fcf7
commit 98b9ddac76
5 changed files with 49 additions and 36 deletions

View File

@ -88,7 +88,6 @@
}
; draw all edges of the object
; @todo crashes with array index out of bounds in stackvm
for uword edge in edges {
ubyte e_from = msb(edge)
ubyte e_to = lsb(edge)

View File

@ -11,49 +11,60 @@
str text = "hello\n"
sub start() {
c64scr.print_ub(X)
c64.CHROUT('\n')
c64scr.print("loop str\n")
rpt:
vm_write_str("\nregular for loop byte\n")
for ubyte x in 10 to 15 {
vm_write_num(x)
vm_write_char(',')
}
vm_write_str("\nregular for loop word\n")
for uword y in 500 to 505 {
vm_write_num(y)
vm_write_char(',')
}
vm_write_str("\nloop str\n")
for ubyte c in text {
c64scr.print_ub(c)
c64.CHROUT(',')
vm_write_num(c)
vm_write_char(',')
}
c64scr.print("\nloop ub\n")
vm_write_str("\nloop ub\n")
for ubyte ub in ubarray{
c64scr.print_ub(ub)
c64.CHROUT(',')
vm_write_num(ub)
vm_write_char(',')
}
c64scr.print("\nloop b\n")
vm_write_str("\nloop b\n")
for byte b in barray {
c64scr.print_b(b)
c64.CHROUT(',')
vm_write_num(b)
vm_write_char(',')
}
c64scr.print("\nloop uw\n")
vm_write_str("\nloop uw\n")
for uword uw in uwarray {
c64scr.print_uw(uw)
c64.CHROUT(',')
vm_write_num(uw)
vm_write_char(',')
}
c64scr.print("\nloop w\n")
vm_write_str("\nloop w\n")
for word w in warray {
c64scr.print_w(w)
c64.CHROUT(',')
vm_write_num(w)
vm_write_char(',')
}
c64scr.print("\nloop f\n")
vm_write_str("\nloop f\n")
for float f in farray {
c64flt.print_f(f)
c64.CHROUT(',')
vm_write_num(f)
vm_write_char(',')
}
goto rpt
ending:
c64scr.print("\nending\n")
c64scr.print_ub(X)
c64.CHROUT('\n')
vm_write_str("\nending\n")
}
}

View File

@ -180,7 +180,7 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
if(forLoop.iterable !is RangeExpr) {
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
if(existing==null) {
// create loop iteration counter variable
// create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, null, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)

View File

@ -105,7 +105,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
if(decl.type!=VarDeclType.VAR || decl.value==null)
return decl
// for variables that are not on the heap (so: byte, word, float),
// regarding variables that are not on the heap (so: byte, word, float),
// replace the var decl with an assignment and add a new vardecl with the default constant value.
if(decl.datatype in NumericDatatypes) {
val scope = decl.definingScope()

View File

@ -1667,13 +1667,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val loopLabel = makeLabel("loop")
val continueLabel = makeLabel("continue")
val breakLabel = makeLabel("break")
val indexVarType = if (numElements <= 255) DataType.UBYTE else DataType.UWORD
val indexVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl
continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel)
val zero = Value(if (numElements <= 255) DataType.UBYTE else DataType.UWORD, 0)
prog.instr(opcodePush(zero.type), zero)
prog.instr(opcodePopvar(zero.type), callLabel = "Y")
// set the index var to zero before the loop
prog.instr(opcodePush(indexVarType), Value(indexVarType, 0))
prog.instr(opcodePopvar(indexVarType), callLabel = indexVar.scopedname)
// loop starts here
prog.label(loopLabel)
val assignTarget = if(loop.loopRegister!=null)
AssignTarget(loop.loopRegister, null, null, loop.position)
@ -1689,14 +1693,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(loop.body)
prog.label(continueLabel)
val loopCounterVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl
prog.instr(opcodeIncvar(zero.type), callLabel = loopCounterVar.scopedname)
prog.instr(opcodeIncvar(indexVarType), callLabel = indexVar.scopedname)
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value.
prog.instr(opcodePush(zero.type), Value(zero.type, numElements))
prog.instr(opcodePushvar(zero.type), callLabel = loopCounterVar.scopedname)
prog.instr(opcodeSub(zero.type))
if(zero.type==DataType.UWORD)
prog.instr(opcodePush(indexVarType), Value(indexVarType, numElements))
prog.instr(opcodePushvar(indexVarType), callLabel = indexVar.scopedname)
prog.instr(opcodeSub(indexVarType))
if(indexVarType==DataType.UWORD)
prog.instr(Opcode.JNZW, callLabel = loopLabel)
else
prog.instr(Opcode.JNZ, callLabel = loopLabel)
@ -1735,7 +1738,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel)
prog.instr(opcodePush(varDt), Value(varDt, range.first))
prog.instr(opcodePush(varDt), Value(varDt, range.first)) // @todo use VariableInitializationStatement instead?? (like other for loop)
prog.instr(opcodePopvar(varDt), callLabel = varname)
prog.label(loopLabel)
translate(body)