mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
for loop generates working code for the most often occurring loop scenarios
This commit is contained in:
parent
f84e06bdeb
commit
4174d49fb3
@ -8,38 +8,62 @@ sub start() -> () {
|
|||||||
byte from = 0
|
byte from = 0
|
||||||
byte last = 5
|
byte last = 5
|
||||||
|
|
||||||
if (i>last) {
|
word iw
|
||||||
_vm_write_num(100)
|
|
||||||
|
word fromw = 0
|
||||||
|
word lastw = 5
|
||||||
|
|
||||||
|
for i in 10 to 1 step -1 {
|
||||||
|
_vm_write_num(i)
|
||||||
_vm_write_char($8d)
|
_vm_write_char($8d)
|
||||||
}
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
|
||||||
|
for i in 10 to 0 step -1 {
|
||||||
|
_vm_write_num(i)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
|
||||||
|
for i in from to last {
|
||||||
|
_vm_write_num(i)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
|
||||||
|
from=250
|
||||||
|
last=255
|
||||||
|
for i in from to last {
|
||||||
|
_vm_write_num(i)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
|
||||||
|
fromw=65530
|
||||||
|
lastw=65535
|
||||||
|
for iw in fromw to lastw {
|
||||||
|
_vm_write_num(iw)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
|
||||||
|
|
||||||
; for i in from to last {
|
from = 5
|
||||||
; _vm_write_num(i)
|
last = 1
|
||||||
; _vm_write_char($8d)
|
|
||||||
; }
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
|
|
||||||
; from=250
|
fromw = 1
|
||||||
; last=255
|
lastw = 5
|
||||||
; for i in from to last {
|
|
||||||
; _vm_write_num(i)
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
; }
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; from = 8
|
|
||||||
; last = 0
|
|
||||||
;
|
|
||||||
; for i in from to last step -1 {
|
|
||||||
; _vm_write_num(i)
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
; }
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
; _vm_write_char($8d)
|
|
||||||
|
|
||||||
|
for iw in fromw to lastw step 1 { ;@todo last 0
|
||||||
|
_vm_write_num(iw)
|
||||||
|
_vm_write_char($8d)
|
||||||
|
}
|
||||||
|
_vm_write_char($8d)
|
||||||
|
_vm_write_char($8d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
* other_stuff ;; optional
|
* other_stuff ;; optional
|
||||||
* _stmt_999_end:
|
* _stmt_999_end:
|
||||||
* nop
|
* nop
|
||||||
|
*
|
||||||
|
* @todo generate more efficient bytecode for the form with just jumps: if_xx goto .. [else goto ..] ?
|
||||||
|
* -> this should translate into just a single branch opcode per goto
|
||||||
*/
|
*/
|
||||||
stackvmProg.line(branch.position)
|
stackvmProg.line(branch.position)
|
||||||
val labelElse = makeLabel("else")
|
val labelElse = makeLabel("else")
|
||||||
@ -258,17 +261,18 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
*
|
*
|
||||||
* or when there is no else block:
|
* or when there is no else block:
|
||||||
* <condition-expression evaluation>
|
* <condition-expression evaluation>
|
||||||
* BNZ _stmt_999_end
|
* BZ _stmt_999_end
|
||||||
* stuff
|
* stuff
|
||||||
* _stmt_999_end:
|
* _stmt_999_end:
|
||||||
* nop
|
* nop
|
||||||
*
|
*
|
||||||
|
* @todo generate more efficient bytecode for the form with just jumps: if(..) goto .. [else goto ..]
|
||||||
*/
|
*/
|
||||||
stackvmProg.line(stmt.position)
|
stackvmProg.line(stmt.position)
|
||||||
translate(stmt.condition)
|
translate(stmt.condition)
|
||||||
val labelEnd = makeLabel("end")
|
val labelEnd = makeLabel("end")
|
||||||
if(stmt.elsepart.isEmpty()) {
|
if(stmt.elsepart.isEmpty()) {
|
||||||
stackvmProg.instr(Opcode.BNZ, callLabel = labelEnd)
|
stackvmProg.instr(Opcode.BZ, callLabel = labelEnd)
|
||||||
translate(stmt.statements)
|
translate(stmt.statements)
|
||||||
stackvmProg.label(labelEnd)
|
stackvmProg.label(labelEnd)
|
||||||
} else {
|
} else {
|
||||||
@ -319,7 +323,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is RangeExpr -> {
|
is RangeExpr -> {
|
||||||
TODO("TRANSLATE range $expr") // todo
|
TODO("TRANSLATE range $expr")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr")
|
val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr")
|
||||||
@ -540,7 +544,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
else if (range.count()==1)
|
else if (range.count()==1)
|
||||||
throw CompilerException("loop over just 1 value should have been optimized away")
|
throw CompilerException("loop over just 1 value should have been optimized away")
|
||||||
if((range.last-range.first) % range.step != 0)
|
if((range.last-range.first) % range.step != 0)
|
||||||
throw CompilerException("range first and last must be inclusive")
|
throw CompilerException("range first and last must be exactly inclusive")
|
||||||
when (loopVarDt) {
|
when (loopVarDt) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
if (range.first < 0 || range.first > 255 || range.last < 0 || range.last > 255)
|
if (range.first < 0 || range.first > 255 || range.last < 0 || range.last > 255)
|
||||||
@ -660,9 +664,17 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
* ..continue statement: goto continue
|
* ..continue statement: goto continue
|
||||||
* ..
|
* ..
|
||||||
* continue:
|
* continue:
|
||||||
* LV ++ / LV-- (if step =1 or step=-1)
|
*
|
||||||
* LV += step (otherwise)
|
* (if we know step is a constant:)
|
||||||
* goto loop
|
* step == 1 ->
|
||||||
|
* LV++
|
||||||
|
* if_nz goto loop ;; acts as overflow check
|
||||||
|
* step == -1 ->
|
||||||
|
* LV--
|
||||||
|
* @todo some condition to check for not overflow , jump to loop
|
||||||
|
* (not constant or other step:
|
||||||
|
* LV += step ; @todo implement overflow on the appropriate arithmetic operations
|
||||||
|
* if_vc goto loop ;; not overflowed
|
||||||
* break:
|
* break:
|
||||||
* nop
|
* nop
|
||||||
*/
|
*/
|
||||||
@ -687,6 +699,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
|
|
||||||
stackvmProg.label(loopLabel)
|
stackvmProg.label(loopLabel)
|
||||||
if(literalStepValue!=null) {
|
if(literalStepValue!=null) {
|
||||||
|
// Step is a constant. We can optimize some stuff!
|
||||||
val loopVar =
|
val loopVar =
|
||||||
if(varname!=null)
|
if(varname!=null)
|
||||||
IdentifierReference(varname, range.position)
|
IdentifierReference(varname, range.position)
|
||||||
@ -708,34 +721,49 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
ifstmt.linkParents(range.parent)
|
ifstmt.linkParents(range.parent)
|
||||||
translate(ifstmt)
|
translate(ifstmt)
|
||||||
} else {
|
} else {
|
||||||
// generate code for the whole if statement
|
// Step is a variable. We can't optimize anything...
|
||||||
TODO("code for non-constant step comparison")
|
TODO("code for non-constant step comparison of LV")
|
||||||
}
|
}
|
||||||
|
|
||||||
stackvmProg.label("body_goes_here") // todo weg
|
translate(body)
|
||||||
|
stackvmProg.label(continueLabel)
|
||||||
|
val lvTarget = makeAssignmentTarget()
|
||||||
|
lvTarget.linkParents(range.parent)
|
||||||
|
val targetStatement: VarDecl? =
|
||||||
|
if(lvTarget.identifier!=null) {
|
||||||
|
lvTarget.identifier.targetStatement(namespace) as VarDecl
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
// translate(body)
|
when (literalStepValue) {
|
||||||
// stackvmProg.label(continueLabel)
|
1 -> {
|
||||||
// when (literalStepValue) {
|
// LV++
|
||||||
// 1 -> {
|
val postIncr = PostIncrDecr(lvTarget, "++", range.position)
|
||||||
// // LV++
|
postIncr.linkParents(range.parent)
|
||||||
// val postIncr = PostIncrDecr(makeAssignmentTarget(), "++", range.position)
|
translate(postIncr)
|
||||||
// postIncr.linkParents(range.parent)
|
if(lvTarget.register!=null)
|
||||||
// translate(postIncr)
|
stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, stringvalue=lvTarget.register.toString()))
|
||||||
// }
|
else
|
||||||
// -1 -> {
|
stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, stringvalue=targetStatement!!.scopedname))
|
||||||
// // LV--
|
val branch = BranchStatement(
|
||||||
// val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
|
BranchCondition.NZ,
|
||||||
// postIncr.linkParents(range.parent)
|
listOf(Jump(null, null, loopLabel, range.position)),
|
||||||
// translate(postIncr)
|
emptyList(), range.position)
|
||||||
// }
|
branch.linkParents(range.parent)
|
||||||
// else -> {
|
translate(branch)
|
||||||
// // LV += step
|
}
|
||||||
// val addAssignment = Assignment(makeAssignmentTarget(), "+=", range.step, range.position)
|
-1 -> {
|
||||||
// addAssignment.linkParents(range.parent)
|
// LV--
|
||||||
// translate(addAssignment)
|
val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
|
||||||
// }
|
postIncr.linkParents(range.parent)
|
||||||
// }
|
translate(postIncr)
|
||||||
|
TODO("signed numbers and/or special condition still needed for decreasing for loop. Try increasing loop and/or constant loop values instead? At: ${range.position}")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stackvmProg.label(breakLabel)
|
stackvmProg.label(breakLabel)
|
||||||
stackvmProg.instr(Opcode.NOP)
|
stackvmProg.instr(Opcode.NOP)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user