diff --git a/compiler/src/prog8/ast/AstToSourceCode.kt b/compiler/src/prog8/ast/AstToSourceCode.kt index e916cdd8a..08b380c2d 100644 --- a/compiler/src/prog8/ast/AstToSourceCode.kt +++ b/compiler/src/prog8/ast/AstToSourceCode.kt @@ -305,10 +305,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program): output(postIncrDecr.operator) } - override fun visit(contStmt: Continue) { - output("continue") - } - override fun visit(breakStmt: Break) { output("break") } diff --git a/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt b/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt index 3975fea4a..ebec76c0e 100644 --- a/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt +++ b/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt @@ -217,9 +217,6 @@ private fun prog8Parser.StatementContext.toAst() : Statement { val breakstmt = breakstmt()?.toAst() if(breakstmt!=null) return breakstmt - val continuestmt = continuestmt()?.toAst() - if(continuestmt!=null) return continuestmt - val whenstmt = whenstmt()?.toAst() if(whenstmt!=null) return whenstmt @@ -593,8 +590,6 @@ private fun prog8Parser.ForloopContext.toAst(): ForLoop { return ForLoop(loopvar, iterable, scope, toPosition()) } -private fun prog8Parser.ContinuestmtContext.toAst() = Continue(toPosition()) - private fun prog8Parser.BreakstmtContext.toAst() = Break(toPosition()) private fun prog8Parser.WhileloopContext.toAst(): WhileLoop { diff --git a/compiler/src/prog8/ast/processing/AstWalker.kt b/compiler/src/prog8/ast/processing/AstWalker.kt index 3f42c3a02..750e2408b 100644 --- a/compiler/src/prog8/ast/processing/AstWalker.kt +++ b/compiler/src/prog8/ast/processing/AstWalker.kt @@ -88,7 +88,6 @@ abstract class AstWalker { open fun before(branchStatement: BranchStatement, parent: Node): Iterable = emptyList() open fun before(breakStmt: Break, parent: Node): Iterable = emptyList() open fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable = emptyList() - open fun before(contStmt: Continue, parent: Node): Iterable = emptyList() open fun before(decl: VarDecl, parent: Node): Iterable = emptyList() open fun before(directive: Directive, parent: Node): Iterable = emptyList() open fun before(expr: BinaryExpression, parent: Node): Iterable = emptyList() @@ -130,7 +129,6 @@ abstract class AstWalker { open fun after(branchStatement: BranchStatement, parent: Node): Iterable = emptyList() open fun after(breakStmt: Break, parent: Node): Iterable = emptyList() open fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable = emptyList() - open fun after(contStmt: Continue, parent: Node): Iterable = emptyList() open fun after(decl: VarDecl, parent: Node): Iterable = emptyList() open fun after(directive: Directive, parent: Node): Iterable = emptyList() open fun after(expr: BinaryExpression, parent: Node): Iterable = emptyList() @@ -309,11 +307,6 @@ abstract class AstWalker { track(after(postIncrDecr, parent), postIncrDecr, parent) } - fun visit(contStmt: Continue, parent: Node) { - track(before(contStmt, parent), contStmt, parent) - track(after(contStmt, parent), contStmt, parent) - } - fun visit(breakStmt: Break, parent: Node) { track(before(breakStmt, parent), breakStmt, parent) track(after(breakStmt, parent), breakStmt, parent) diff --git a/compiler/src/prog8/ast/processing/IAstVisitor.kt b/compiler/src/prog8/ast/processing/IAstVisitor.kt index 93f6a8250..990afa478 100644 --- a/compiler/src/prog8/ast/processing/IAstVisitor.kt +++ b/compiler/src/prog8/ast/processing/IAstVisitor.kt @@ -95,9 +95,6 @@ interface IAstVisitor { postIncrDecr.target.accept(this) } - fun visit(contStmt: Continue) { - } - fun visit(breakStmt: Break) { } diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 4d6b4d4fc..6a78c20ee 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -148,18 +148,6 @@ class ReturnFromIrq(override val position: Position) : Return(null, position) { override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here") } -class Continue(override val position: Position) : Statement() { - override lateinit var parent: Node - - override fun linkParents(parent: Node) { - this.parent=parent - } - - override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here") - override fun accept(visitor: IAstVisitor) = visitor.visit(this) - override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) -} - class Break(override val position: Position) : Statement() { override lateinit var parent: Node diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index b044a9cf3..36ecb64fc 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -43,13 +43,11 @@ internal class AsmGen(private val program: Program, private val assignmentAsmGen = AssignmentAsmGen(program, errors, this) private val expressionsAsmGen = ExpressionsAsmGen(program, this) internal val loopEndLabels = ArrayDeque() - internal val loopContinueLabels = ArrayDeque() internal val blockLevelVarInits = mutableMapOf>() override fun compileToAssembly(optimize: Boolean): IAssemblyProgram { assemblyLines.clear() loopEndLabels.clear() - loopContinueLabels.clear() println("Generating assembly code... ") @@ -638,7 +636,6 @@ internal class AsmGen(private val program: Program, is BranchStatement -> translate(stmt) is IfStatement -> translate(stmt) is ForLoop -> forloopsAsmGen.translate(stmt) - is Continue -> out(" jmp ${loopContinueLabels.peek()}") is Break -> out(" jmp ${loopEndLabels.peek()}") is WhileLoop -> translate(stmt) is RepeatLoop -> translate(stmt) @@ -674,11 +671,11 @@ internal class AsmGen(private val program: Program, } private fun translate(stmt: RepeatLoop) { + // TODO more optimized code possible now that continue is gone? val repeatLabel = makeLabel("repeat") val endLabel = makeLabel("repeatend") val counterLabel = makeLabel("repeatcounter") loopEndLabels.push(endLabel) - loopContinueLabels.push(repeatLabel) when (stmt.iterations) { null -> { @@ -737,7 +734,6 @@ internal class AsmGen(private val program: Program, } loopEndLabels.pop() - loopContinueLabels.pop() } private fun repeatWordCountInAY(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) { @@ -778,10 +774,10 @@ $endLabel""") } private fun translate(stmt: WhileLoop) { + // TODO more optimized code possible now that continue is gone? val whileLabel = makeLabel("while") val endLabel = makeLabel("whileend") loopEndLabels.push(endLabel) - loopContinueLabels.push(whileLabel) out(whileLabel) expressionsAsmGen.translateExpression(stmt.condition) val conditionDt = stmt.condition.inferType(program) @@ -802,14 +798,13 @@ $endLabel""") out(" jmp $whileLabel") out(endLabel) loopEndLabels.pop() - loopContinueLabels.pop() } private fun translate(stmt: UntilLoop) { + // TODO more optimized code possible now that continue is gone? val repeatLabel = makeLabel("repeat") val endLabel = makeLabel("repeatend") loopEndLabels.push(endLabel) - loopContinueLabels.push(repeatLabel) out(repeatLabel) translate(stmt.body) expressionsAsmGen.translateExpression(stmt.untilCondition) @@ -829,7 +824,6 @@ $endLabel""") } out(endLabel) loopEndLabels.pop() - loopContinueLabels.pop() } private fun translate(stmt: WhenStatement) { diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt index abfd2c8e2..23e4cf5f0 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt @@ -14,9 +14,8 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX import prog8.compiler.toHex import kotlin.math.absoluteValue -// todo optimized loop code for common simple cases 0..N, N..0, >=1..N , N..>=1 where N<=255 // todo choose more efficient comparisons to avoid needless lda's -// todo optimize common case when step == 2 or -2 +// todo optimized code for step == 2 or -2 // todo allocate loop counter variable dynamically, preferrably on zeropage internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { @@ -42,11 +41,11 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen: } private fun translateForOverNonconstRange(stmt: ForLoop, iterableDt: DataType, range: RangeExpr) { + // TODO more optimized code possible now that continue is gone? + val loopLabel = asmgen.makeLabel("for_loop") val endLabel = asmgen.makeLabel("for_end") - val continueLabel = asmgen.makeLabel("for_continue") asmgen.loopEndLabels.push(endLabel) - asmgen.loopContinueLabels.push(continueLabel) val stepsize=range.step.constValue(program)!!.number.toInt() when(iterableDt) { DataType.ARRAY_B, DataType.ARRAY_UB -> { @@ -66,7 +65,7 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen: $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel lda $varname + lda $varname cmp $ESTACK_LO_PLUS1_HEX,x beq $endLabel $incdec $varname @@ -88,7 +87,7 @@ $endLabel inx""") $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel lda $varname""") + lda $varname""") if(stepsize>0) { asmgen.out(""" clc @@ -248,15 +247,13 @@ $endLabel inx""") } asmgen.loopEndLabels.pop() - asmgen.loopContinueLabels.pop() } private fun translateForOverIterableVar(stmt: ForLoop, iterableDt: DataType, ident: IdentifierReference) { + // TODO more optimized code possible now that continue is gone? val loopLabel = asmgen.makeLabel("for_loop") val endLabel = asmgen.makeLabel("for_end") - val continueLabel = asmgen.makeLabel("for_continue") asmgen.loopEndLabels.push(endLabel) - asmgen.loopContinueLabels.push(continueLabel) val iterableName = asmgen.asmIdentifierName(ident) val decl = ident.targetVarDecl(program.namespace)!! when(iterableDt) { @@ -271,7 +268,7 @@ $loopLabel lda ${65535.toHex()} ; modified asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel inc $loopLabel+1 + inc $loopLabel+1 bne $loopLabel inc $loopLabel+2 bne $loopLabel @@ -293,7 +290,7 @@ $modifiedLabel lda ${65535.toHex()},y ; modified""") asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel ldy $counterLabel + ldy $counterLabel iny cpy #${length and 255} beq $endLabel @@ -325,7 +322,7 @@ $modifiedLabel2 lda ${65535.toHex()},y ; modified sta $loopvarName+1""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel ldy $counterLabel + ldy $counterLabel iny iny cpy #${length and 255} @@ -340,57 +337,34 @@ $endLabel""") else -> throw AssemblyError("can't iterate over $iterableDt") } asmgen.loopEndLabels.pop() - asmgen.loopContinueLabels.pop() } private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) { - // TODO: optimize loop code when the range is < 256 iterations - if (range.isEmpty()) - throw AssemblyError("empty range") + if (range.isEmpty() || range.step==0) + throw AssemblyError("empty range or step 0") + if(iterableDt==DataType.ARRAY_B || iterableDt==DataType.ARRAY_UB) { + if(range.step==1 && range.first>=0 && range.last <= 255 && range.last>range.first) return translateForSimpleByteRangeAsc(stmt, range) + if(range.step==-1 && range.first<=255 && range.first >=0 && range.last=0 && range.last <= 255 && range.last>range.first) return translateForSimpleWordRange255Asc(stmt, range) + if(range.step==-1 && range.first<=255 && range.first >=0 && range.last=0 && range.last <= 65535 && range.last>range.first) return translateForSimpleWordRange65535Asc(stmt, range) + if(range.step==-1 && range.first<=65535 && range.first >=0 && range.last { + // loop over byte range via loopvar, step > 1 or < -1 val counterLabel = asmgen.makeLabel("for_counter") - // loop over byte range via loopvar val varname = asmgen.asmIdentifierName(stmt.loopVar) when { - range.step==1 -> { - // step = 1 - asmgen.out(""" - lda #${range.first} - sta $varname - lda #${range.last-range.first+1 and 255} - sta $counterLabel -$loopLabel""") - asmgen.translate(stmt.body) - asmgen.out(""" -$continueLabel dec $counterLabel - beq $endLabel - inc $varname - jmp $loopLabel -$counterLabel .byte 0 -$endLabel""") - } - range.step==-1 -> { - // step = -1 - asmgen.out(""" - lda #${range.first} - sta $varname - lda #${range.first-range.last+1 and 255} - sta $counterLabel -$loopLabel""") - asmgen.translate(stmt.body) - asmgen.out(""" -$continueLabel dec $counterLabel - beq $endLabel - dec $varname - jmp $loopLabel -$counterLabel .byte 0 -$endLabel""") + range.step==1 || range.step==-1 -> { + throw AssemblyError("step 1 and -1 should have been handled specifically") } range.step >= 2 -> { // step >= 2 @@ -402,7 +376,7 @@ $endLabel""") $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel dec $counterLabel + dec $counterLabel beq $endLabel lda $varname clc @@ -422,7 +396,7 @@ $endLabel""") $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel dec $counterLabel + dec $counterLabel beq $endLabel lda $varname sec @@ -435,56 +409,59 @@ $endLabel""") } } DataType.ARRAY_W, DataType.ARRAY_UW -> { - // loop over word range via loopvar + // loop over word range via loopvar, step > 1 or < -1 val varname = asmgen.asmIdentifierName(stmt.loopVar) when { - range.step == 1 -> { - // word, step = 1 - val lastValue = range.last+1 - asmgen.out(""" - lda #<${range.first} - ldy #>${range.first} - sta $varname - sty $varname+1 -$loopLabel""") - asmgen.translate(stmt.body) - asmgen.out(""" -$continueLabel inc $varname - bne + - inc $varname+1 -+ lda $varname - cmp #<$lastValue - bne + - lda $varname+1 - cmp #>$lastValue - beq $endLabel -+ jmp $loopLabel -$endLabel""") - } - range.step == -1 -> { - // word, step = 1 - val lastValue = range.last-1 - asmgen.out(""" - lda #<${range.first} - ldy #>${range.first} - sta $varname - sty $varname+1 -$loopLabel""") - asmgen.translate(stmt.body) - asmgen.out(""" -$continueLabel lda $varname - bne + - dec $varname+1 -+ dec $varname - lda $varname - cmp #<$lastValue - bne + - lda $varname+1 - cmp #>$lastValue - beq $endLabel -+ jmp $loopLabel -$endLabel""") + range.step==1 || range.step==-1 -> { + throw AssemblyError("step 1 and -1 should have been handled specifically") } +// range.step == 1 -> { +// // word, step = 1 +// val lastValue = range.last+1 +// asmgen.out(""" +// lda #<${range.first} +// ldy #>${range.first} +// sta $varname +// sty $varname+1 +//$loopLabel""") +// asmgen.translate(stmt.body) +// asmgen.out(""" +// inc $varname +// bne + +// inc $varname+1 +//+ lda $varname +// cmp #<$lastValue +// bne + +// lda $varname+1 +// cmp #>$lastValue +// beq $endLabel +//+ jmp $loopLabel +//$endLabel""") +// } +// range.step == -1 -> { +// // word, step = 1 +// val lastValue = range.last-1 +// asmgen.out(""" +// lda #<${range.first} +// ldy #>${range.first} +// sta $varname +// sty $varname+1 +//$loopLabel""") +// asmgen.translate(stmt.body) +// asmgen.out(""" +// lda $varname +// bne + +// dec $varname+1 +//+ dec $varname +// lda $varname +// cmp #<$lastValue +// bne + +// lda $varname+1 +// cmp #>$lastValue +// beq $endLabel +//+ jmp $loopLabel +//$endLabel""") +// } range.step >= 2 -> { // word, step >= 2 // note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence @@ -497,7 +474,7 @@ $endLabel""") $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel clc + clc lda $varname adc #<${range.step} sta $varname @@ -525,7 +502,7 @@ $endLabel""") $loopLabel""") asmgen.translate(stmt.body) asmgen.out(""" -$continueLabel sec + sec lda $varname sbc #<${range.step.absoluteValue} sta $varname @@ -546,7 +523,102 @@ $endLabel""") else -> throw AssemblyError("range expression can only be byte or word") } asmgen.loopEndLabels.pop() - asmgen.loopContinueLabels.pop() + } + + private fun translateForSimpleByteRangeAsc(stmt: ForLoop, range: IntProgression) { + val loopLabel = asmgen.makeLabel("for_loop") + val endLabel = asmgen.makeLabel("for_end") + asmgen.loopEndLabels.push(endLabel) + val varname = asmgen.asmIdentifierName(stmt.loopVar) + if (range.last == 255) { + asmgen.out(""" + lda #${range.first} + sta $varname +$loopLabel""") + asmgen.translate(stmt.body) + asmgen.out(""" + inc $varname + bne $loopLabel +$endLabel""") + } else { + asmgen.out(""" + lda #${range.first} + sta $varname +$loopLabel""") + asmgen.translate(stmt.body) + asmgen.out(""" + lda $varname + cmp #${range.last} + beq $endLabel + inc $varname + bne $loopLabel +$endLabel""") + } + asmgen.loopEndLabels.pop() + } + + private fun translateForSimpleByteRangeDesc(stmt: ForLoop, range: IntProgression) { + val loopLabel = asmgen.makeLabel("for_loop") + val endLabel = asmgen.makeLabel("for_end") + asmgen.loopEndLabels.push(endLabel) + val varname = asmgen.asmIdentifierName(stmt.loopVar) + when (range.last) { + 0 -> { + asmgen.out(""" + lda #${range.first} + sta $varname +$loopLabel""") + asmgen.translate(stmt.body) + asmgen.out(""" + lda $varname + beq $endLabel + dec $varname + jmp $loopLabel +$endLabel""") + } + 1 -> { + asmgen.out(""" + lda #${range.first} + sta $varname +$loopLabel""") + asmgen.translate(stmt.body) + asmgen.out(""" + dec $varname + bne $loopLabel +$endLabel""") + } + else -> { + asmgen.out(""" + lda #${range.first} + sta $varname +$loopLabel""") + asmgen.translate(stmt.body) + asmgen.out(""" + lda $varname + cmp #${range.last} + beq $endLabel + dec $varname + bne $loopLabel +$endLabel""") + } + } + asmgen.loopEndLabels.pop() + } + + private fun translateForSimpleWordRange255Asc(stmt: ForLoop, range: IntProgression) { + TODO("Not yet implemented") + } + + private fun translateForSimpleWordRange255Desc(stmt: ForLoop, range: IntProgression) { + TODO("Not yet implemented") + } + + private fun translateForSimpleWordRange65535Asc(stmt: ForLoop, range: IntProgression) { + TODO("Not yet implemented") + } + + private fun translateForSimpleWordRange65535Desc(stmt: ForLoop, range: IntProgression) { + TODO("Not yet implemented") } } diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index 23dcac11e..f649cb1ca 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -14,11 +14,6 @@ import prog8.functions.BuiltinFunctions import kotlin.math.floor -/* - TODO: remove unreachable code after return and exit() -*/ - - internal class StatementOptimizer(private val program: Program, private val errors: ErrorReporter) : AstWalker() { @@ -257,9 +252,9 @@ internal class StatementOptimizer(private val program: Program, val constvalue = untilLoop.untilCondition.constValue(program) if(constvalue!=null) { if(constvalue.asBooleanValue) { - // always true -> keep only the statement block (if there are no continue and break statements) + // always true -> keep only the statement block (if there are no break statements) errors.warn("condition is always true", untilLoop.untilCondition.position) - if(!hasContinueOrBreak(untilLoop.body)) + if(!hasBreak(untilLoop.body)) return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent)) } else { // always false @@ -495,7 +490,7 @@ internal class StatementOptimizer(private val program: Program, return linesToRemove } - private fun hasContinueOrBreak(scope: INameScope): Boolean { + private fun hasBreak(scope: INameScope): Boolean { class Searcher: IAstVisitor { @@ -504,10 +499,6 @@ internal class StatementOptimizer(private val program: Program, override fun visit(breakStmt: Break) { count++ } - - override fun visit(contStmt: Continue) { - count++ - } } val s=Searcher() diff --git a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt b/compiler/src/prog8/optimizer/UnusedCodeRemover.kt index 9a78efded..fb4b8c0c5 100644 --- a/compiler/src/prog8/optimizer/UnusedCodeRemover.kt +++ b/compiler/src/prog8/optimizer/UnusedCodeRemover.kt @@ -6,6 +6,9 @@ import prog8.ast.processing.AstWalker import prog8.ast.processing.IAstModification import prog8.ast.statements.Block +/* + TODO: remove unreachable code after return and exit() +*/ internal class UnusedCodeRemover: AstWalker() { diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 11d3534f7..cdda09e7a 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -397,6 +397,8 @@ The *repeat* loop is used as a short notation of a for loop where the loop varia You can also create loops by using the ``goto`` statement, but this should usually be avoided. +Breaking out of a loop prematurely is possible with the ``break`` statement. + .. attention:: The value of the loop variable after executing the loop *is undefined*. Don't use it immediately after the loop without first assigning a new value to it! diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 9da90fb04..1b8009c17 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -559,7 +559,6 @@ You can use a single statement, or a statement block like in the example below:: for in [ step ] { ; do something... break ; break out of the loop - continue ; immediately enter next iteration } For example, this is a for loop using a byte variable ``i``, defined before, to loop over a certain range of numbers:: @@ -592,7 +591,6 @@ You can use a single statement, or a statement block like in the example below:: while { ; do something... break ; break out of the loop - continue ; immediately enter next iteration } @@ -605,7 +603,6 @@ You can use a single statement, or a statement block like in the example below:: do { ; do something... break ; break out of the loop - continue ; immediately enter next iteration } until diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 25a5d17f4..257a9473d 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,9 +2,10 @@ TODO ==== -- finalize (most) of the still missing "new" assignment asm code generation -- aliases for imported symbols for example perhaps '%alias print = c64scr.print' -- option to load library files from a directory instead of the embedded ones (easier library development/debugging) +- get rid of all TODO's ;-) +- allow declaring arrays on specific memory location and page-aligned +- option to load the built-inlibrary files from a directory instead of the embedded ones (for easier library development/debugging) +- aliases for imported symbols for example perhaps '%alias print = c64scr.print' ? - investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs - see if we can group some errors together for instance the (now single) errors about unidentified symbols diff --git a/examples/mfbench/romsum-p8.p8 b/examples/mfbench/romsum-p8.p8 new file mode 100644 index 000000000..05c4567ad --- /dev/null +++ b/examples/mfbench/romsum-p8.p8 @@ -0,0 +1,74 @@ +%import c64utils + +main { + + const uword rom = $e000 + + sub sumrom() -> uword { + uword p = rom + uword s = 0 + ubyte i + repeat $20 { + for i in 0 to $ff { + s += @(p+i) + } + p += $100 + } + return s + } + + sub start() { + benchcommon.begin() + ubyte i + for i in 0 to 5 { + c64scr.print_uw(sumrom()) + c64.CHROUT('\n') + } + benchcommon.end() + } +} + + +benchcommon { + ubyte last_time0 = 0 + ubyte last_time1 = 0 + ubyte last_time2 = 0 + ubyte time_start0 = 0 + ubyte time_start1 = 0 + ubyte time_start2 = 0 + + + asmsub read_time () clobbers(A,X,Y) { + %asm {{ + jsr $FFDE + sta last_time0 + stx last_time1 + sty last_time2 + rts + }} + } + + sub begin() { + benchcommon.read_time() + benchcommon.time_start0 = benchcommon.last_time0 + benchcommon.time_start1 = benchcommon.last_time1 + benchcommon.time_start2 = benchcommon.last_time2 + } + + sub end() { + benchcommon.read_time() + + c64scr.print_ubhex(benchcommon.time_start2, false) + c64scr.print_ubhex(benchcommon.time_start1, false) + c64scr.print_ubhex(benchcommon.time_start0, false) + c64.CHROUT('\n') + + c64scr.print_ubhex(benchcommon.last_time2, false) + c64scr.print_ubhex(benchcommon.last_time1, false) + c64scr.print_ubhex(benchcommon.last_time0, false) + c64.CHROUT('\n') + + void c64scr.input_chars($c000) + } +} + diff --git a/examples/mfbench/sieve-p8.p8 b/examples/mfbench/sieve-p8.p8 new file mode 100644 index 000000000..ba937654b --- /dev/null +++ b/examples/mfbench/sieve-p8.p8 @@ -0,0 +1,88 @@ +%import c64utils + +main { + + const uword COUNT = 16384 + const uword SQRT_COUNT = 128 + const uword Sieve = $4000 + + sub sieve_round() { + uword S + ubyte I = 2 + memset(Sieve, COUNT, 0) + while I < SQRT_COUNT { + if @(Sieve + I) == 0 { + S = Sieve + (I << 1) + while S < Sieve + COUNT { + @(S) = 1 + S += I + } + } + I ++ + } + } + + sub start() { + benchcommon.begin() + + sieve_round() + sieve_round() + sieve_round() + sieve_round() + sieve_round() + + sieve_round() + sieve_round() + sieve_round() + sieve_round() + sieve_round() + + benchcommon.end() + } +} + + + +benchcommon { + ubyte last_time0 = 0 + ubyte last_time1 = 0 + ubyte last_time2 = 0 + ubyte time_start0 = 0 + ubyte time_start1 = 0 + ubyte time_start2 = 0 + + + asmsub read_time () clobbers(A,X,Y) { + %asm {{ + jsr $FFDE + sta last_time0 + stx last_time1 + sty last_time2 + rts + }} + } + + sub begin() { + benchcommon.read_time() + benchcommon.time_start0 = benchcommon.last_time0 + benchcommon.time_start1 = benchcommon.last_time1 + benchcommon.time_start2 = benchcommon.last_time2 + } + + sub end() { + benchcommon.read_time() + + c64scr.print_ubhex(benchcommon.time_start2, false) + c64scr.print_ubhex(benchcommon.time_start1, false) + c64scr.print_ubhex(benchcommon.time_start0, false) + c64.CHROUT('\n') + + c64scr.print_ubhex(benchcommon.last_time2, false) + c64scr.print_ubhex(benchcommon.last_time1, false) + c64scr.print_ubhex(benchcommon.last_time0, false) + c64.CHROUT('\n') + + void c64scr.input_chars($c000) + } +} + diff --git a/examples/test.p8 b/examples/test.p8 index 18d53a3c7..07b5ff881 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,49 +2,97 @@ %import c64utils %import c64flt %zeropage basicsafe -%option enable_floats main { sub start() { + ubyte counterb + uword counterw - ubyte wv - ubyte wv2 - wv = wv + wv + wv + for counterb in 0 to 10 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') -; wv *= wv2 -; -; wv += 10 -; wv += 20 -; wv += 30 -; -; wv += 1 + wv2 -; wv += 2 + wv2 -; wv += 3 + wv2 -; -; wv += wv2 + 1 -; wv += wv2 + 2 -; wv += wv2 + 3 -; -; wv = wv + 1 + wv2 -; wv = wv + 2 + wv2 -; wv = wv + 3 + wv2 -; -; wv = 1 + wv2 + wv -; wv = 2 + wv2 + wv -; wv = 3 + wv2 + wv -; -; wv = wv + wv2 + 1 -; wv = wv + wv2 + 2 -; wv = wv + wv2 + 3 -; -; wv = wv2 + 1 + wv -; wv = wv2 + 2 + wv -; wv = wv2 + 3 + wv + for counterb in 10 to 30 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') - wv = wv2 + wv + 1 - wv = wv2 + wv + 2 - wv = wv2 + wv + 3 + for counterb in 250 to 255 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterb in 10 to 0 step -1 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterb in 10 to 1 step -1 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterb in 30 to 10 step -1 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterb in 255 to 250 step -1 { + c64scr.print_ub(counterb) + c64.CHROUT(',') + } + c64.CHROUT('\n') + c64.CHROUT('\n') + + for counterw in 0 to 10 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 10 to 30 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 250 to 255 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 10 to 0 step -1 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 10 to 1 step -1 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 30 to 10 step -1 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for counterw in 255 to 250 step -1 { + c64scr.print_uw(counterw) + c64.CHROUT(',') + } + c64.CHROUT('\n') } } diff --git a/parser/antlr/prog8.g4 b/parser/antlr/prog8.g4 index bafdd9d9a..790f2887d 100644 --- a/parser/antlr/prog8.g4 +++ b/parser/antlr/prog8.g4 @@ -98,7 +98,6 @@ statement : | repeatloop | whenstmt | breakstmt - | continuestmt | labeldef ; @@ -214,8 +213,6 @@ returnstmt : 'return' expression? ; breakstmt : 'break'; -continuestmt: 'continue'; - identifier : NAME ; scoped_identifier : NAME ('.' NAME)* ;