diff --git a/compiler/examples/cube3d.p8 b/compiler/examples/cube3d.p8 index 854484a6c..f8e2308d2 100644 --- a/compiler/examples/cube3d.p8 +++ b/compiler/examples/cube3d.p8 @@ -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) diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 873ba8cba..eb79cdc81 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -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") } } diff --git a/compiler/src/prog8/ast/AstIdentifiersChecker.kt b/compiler/src/prog8/ast/AstIdentifiersChecker.kt index f992fa149..76c00fe75 100644 --- a/compiler/src/prog8/ast/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/ast/AstIdentifiersChecker.kt @@ -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) diff --git a/compiler/src/prog8/ast/StmtReorderer.kt b/compiler/src/prog8/ast/StmtReorderer.kt index c0f94c122..c06c921e7 100644 --- a/compiler/src/prog8/ast/StmtReorderer.kt +++ b/compiler/src/prog8/ast/StmtReorderer.kt @@ -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() diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 4d0d0a771..60cd388a1 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -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)