From f5db31b8ff35f15087e098cd88461c86d5641d85 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 24 Sep 2020 19:26:07 +0200 Subject: [PATCH] do..until condition can now refer to variables defined in the loop's inner scope. --- compiler/src/prog8/ast/AstToSourceCode.kt | 2 +- .../src/prog8/ast/processing/AstChecker.kt | 4 +- .../src/prog8/ast/processing/AstWalker.kt | 2 +- .../src/prog8/ast/processing/IAstVisitor.kt | 2 +- .../src/prog8/ast/statements/AstStatements.kt | 6 +- .../compiler/BeforeAsmGenerationAstChanger.kt | 30 +++ .../compiler/target/c64/codegen/AsmGen.kt | 97 +++----- .../target/c64/codegen/ExpressionsAsmGen.kt | 216 +++++++++++++++++- .../src/prog8/optimizer/StatementOptimizer.kt | 4 +- docs/source/todo.rst | 2 +- examples/test.p8 | 38 ++- 11 files changed, 318 insertions(+), 85 deletions(-) diff --git a/compiler/src/prog8/ast/AstToSourceCode.kt b/compiler/src/prog8/ast/AstToSourceCode.kt index 2e6344c03..25f460c66 100644 --- a/compiler/src/prog8/ast/AstToSourceCode.kt +++ b/compiler/src/prog8/ast/AstToSourceCode.kt @@ -338,7 +338,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program): output("do ") untilLoop.body.accept(this) output(" until ") - untilLoop.untilCondition.accept(this) + untilLoop.condition.accept(this) } override fun visit(returnStmt: Return) { diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 461d9ed78..e411eca76 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -334,8 +334,8 @@ internal class AstChecker(private val program: Program, } override fun visit(untilLoop: UntilLoop) { - if(untilLoop.untilCondition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes) - errors.err("condition value should be an integer type", untilLoop.untilCondition.position) + if(untilLoop.condition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes) + errors.err("condition value should be an integer type", untilLoop.condition.position) super.visit(untilLoop) } diff --git a/compiler/src/prog8/ast/processing/AstWalker.kt b/compiler/src/prog8/ast/processing/AstWalker.kt index 0852af221..d6ea71d50 100644 --- a/compiler/src/prog8/ast/processing/AstWalker.kt +++ b/compiler/src/prog8/ast/processing/AstWalker.kt @@ -348,7 +348,7 @@ abstract class AstWalker { fun visit(untilLoop: UntilLoop, parent: Node) { track(before(untilLoop, parent), untilLoop, parent) - untilLoop.untilCondition.accept(this, untilLoop) + untilLoop.condition.accept(this, untilLoop) untilLoop.body.accept(this, untilLoop) track(after(untilLoop, parent), untilLoop, parent) } diff --git a/compiler/src/prog8/ast/processing/IAstVisitor.kt b/compiler/src/prog8/ast/processing/IAstVisitor.kt index 990afa478..9bf765a6a 100644 --- a/compiler/src/prog8/ast/processing/IAstVisitor.kt +++ b/compiler/src/prog8/ast/processing/IAstVisitor.kt @@ -115,7 +115,7 @@ interface IAstVisitor { } fun visit(untilLoop: UntilLoop) { - untilLoop.untilCondition.accept(this) + untilLoop.condition.accept(this) untilLoop.body.accept(this) } diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 10240ad76..a316af3b3 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -815,19 +815,19 @@ class RepeatLoop(var iterations: Expression?, var body: AnonymousScope, override } class UntilLoop(var body: AnonymousScope, - var untilCondition: Expression, + var condition: Expression, override val position: Position) : Statement() { override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent - untilCondition.linkParents(this) + condition.linkParents(this) body.linkParents(this) } override fun replaceChildNode(node: Node, replacement: Node) { when { - node===untilCondition -> untilCondition = replacement as Expression + node===condition -> condition = replacement as Expression node===body -> body = replacement as AnonymousScope else -> throw FatalAstException("invalid replace") } diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index fdc23c6b8..3c5424cde 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -164,4 +164,34 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E return noModifications } + + override fun after(ifStatement: IfStatement, parent: Node): Iterable { + val binExpr = ifStatement.condition as? BinaryExpression + if(binExpr==null || binExpr.operator !in comparisonOperators) { + // if x -> if x!=0, if x+5 -> if x+5 != 0 + val booleanExpr = BinaryExpression(ifStatement.condition, "!=", NumericLiteralValue.optimalInteger(0, ifStatement.condition.position), ifStatement.condition.position) + return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) + } + return noModifications + } + + override fun after(untilLoop: UntilLoop, parent: Node): Iterable { + val binExpr = untilLoop.condition as? BinaryExpression + if(binExpr==null || binExpr.operator !in comparisonOperators) { + // until x -> until x!=0, until x+5 -> until x+5 != 0 + val booleanExpr = BinaryExpression(untilLoop.condition, "!=", NumericLiteralValue.optimalInteger(0, untilLoop.condition.position), untilLoop.condition.position) + return listOf(IAstModification.ReplaceNode(untilLoop.condition, booleanExpr, untilLoop)) + } + return noModifications + } + + override fun after(whileLoop: WhileLoop, parent: Node): Iterable { + val binExpr = whileLoop.condition as? BinaryExpression + if(binExpr==null || binExpr.operator !in comparisonOperators) { + // while x -> while x!=0, while x+5 -> while x+5 != 0 + val booleanExpr = BinaryExpression(whileLoop.condition, "!=", NumericLiteralValue.optimalInteger(0, whileLoop.condition.position), whileLoop.condition.position) + return listOf(IAstModification.ReplaceNode(whileLoop.condition, booleanExpr, whileLoop)) + } + return noModifications + } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index c7e216b8f..c29ca5eb8 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -845,47 +845,32 @@ $save .byte 0 } private fun translate(stmt: IfStatement) { - when { - stmt.elsepart.containsNoCodeNorVars() -> { - // empty else - expressionsAsmGen.translateExpression(stmt.condition) - translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) - val endLabel = makeLabel("if_end") - out(" beq $endLabel") - translate(stmt.truepart) - out(endLabel) - } - stmt.truepart.containsNoCodeNorVars() -> { - // empty true part - expressionsAsmGen.translateExpression(stmt.condition) - translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) - val endLabel = makeLabel("if_end") - out(" bne $endLabel") - translate(stmt.elsepart) - out(endLabel) - } - else -> { - expressionsAsmGen.translateExpression(stmt.condition) - translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) - val elseLabel = makeLabel("if_else") - val endLabel = makeLabel("if_end") - out(" beq $elseLabel") - translate(stmt.truepart) - out(" jmp $endLabel") - out(elseLabel) - translate(stmt.elsepart) - out(endLabel) - } + checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x ' + val booleanCondition = stmt.condition as BinaryExpression + + if (stmt.elsepart.containsNoCodeNorVars()) { + // empty else + val endLabel = makeLabel("if_end") + expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, endLabel) + translate(stmt.truepart) + out(endLabel) + } + else { + // both true and else parts + val elseLabel = makeLabel("if_else") + val endLabel = makeLabel("if_end") + expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, elseLabel) + translate(stmt.truepart) + out(" jmp $endLabel") + out(elseLabel) + translate(stmt.elsepart) + out(endLabel) } } - private fun translateTestStack(dataType: DataType) { - when(dataType) { - in ByteDatatypes -> out(" inx | lda P8ESTACK_LO,x") - in WordDatatypes -> out(" inx | lda P8ESTACK_LO,x | ora P8ESTACK_HI,x") - DataType.FLOAT -> throw AssemblyError("conditional value should be an integer (boolean)") - else -> throw AssemblyError("non-numerical dt") - } + private fun checkBooleanExpression(condition: Expression) { + if(condition !is BinaryExpression || condition.operator !in comparisonOperators) + throw AssemblyError("expected boolean expression $condition") } private fun translate(stmt: RepeatLoop) { @@ -1004,25 +989,13 @@ $counterVar .byte 0""") } private fun translate(stmt: WhileLoop) { + checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x ' + val booleanCondition = stmt.condition as BinaryExpression val whileLabel = makeLabel("while") val endLabel = makeLabel("whileend") loopEndLabels.push(endLabel) out(whileLabel) - expressionsAsmGen.translateExpression(stmt.condition) - val conditionDt = stmt.condition.inferType(program) - if(!conditionDt.isKnown) - throw AssemblyError("unknown condition dt") - if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes) { - out(" inx | lda P8ESTACK_LO,x | beq $endLabel") - } else { - out(""" - inx - lda P8ESTACK_LO,x - bne + - lda P8ESTACK_HI,x - beq $endLabel -+ """) - } + expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, endLabel) translate(stmt.body) out(" jmp $whileLabel") out(endLabel) @@ -1030,26 +1003,14 @@ $counterVar .byte 0""") } private fun translate(stmt: UntilLoop) { + checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x ' + val booleanCondition = stmt.condition as BinaryExpression val repeatLabel = makeLabel("repeat") val endLabel = makeLabel("repeatend") loopEndLabels.push(endLabel) out(repeatLabel) translate(stmt.body) - expressionsAsmGen.translateExpression(stmt.untilCondition) - val conditionDt = stmt.untilCondition.inferType(program) - if(!conditionDt.isKnown) - throw AssemblyError("unknown condition dt") - if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes) { - out(" inx | lda P8ESTACK_LO,x | beq $repeatLabel") - } else { - out(""" - inx - lda P8ESTACK_LO,x - bne + - lda P8ESTACK_HI,x - beq $repeatLabel -+ """) - } + expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, repeatLabel) out(endLabel) loopEndLabels.pop() } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index 4d77c4a81..3507c6589 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -28,6 +28,220 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } } + internal fun translateComparisonExpressionWithJumpIfFalse(expr: BinaryExpression, jumpIfFalseLabel: String) { + // first, if it is of the form: X , swap the operands around. + var left = expr.left + var right = expr.right + var operator = expr.operator + var leftConstVal = left.constValue(program) + var rightConstVal = right.constValue(program) + if(leftConstVal!=null) { + val tmp = left + left = right + right = tmp + val tmp2 = leftConstVal + leftConstVal = rightConstVal + rightConstVal = tmp2 + when(expr.operator) { + "<" -> operator = ">" + "<=" -> operator = ">=" + ">" -> operator = "<" + ">=" -> operator = "<=" + } + } + + val dt = left.inferType(program).typeOrElse(DataType.STRUCT) + when (operator) { + "==" -> { + when (dt) { + in ByteDatatypes -> { + translateByteEquals(left, right, leftConstVal, rightConstVal) + asmgen.out(" bne $jumpIfFalseLabel") + } + in WordDatatypes -> { + translateWordEquals(left, right, leftConstVal, rightConstVal) + asmgen.out(" bne $jumpIfFalseLabel") + } + DataType.FLOAT -> { + TODO("float eq.") + } + else -> throw AssemblyError("weird operand datatype") + } + } + "!=" -> { + when (dt) { + in ByteDatatypes -> { + translateByteEquals(left, right, leftConstVal, rightConstVal) + asmgen.out(" beq $jumpIfFalseLabel") + } + in WordDatatypes -> { + translateWordEquals(left, right, leftConstVal, rightConstVal) + asmgen.out(" beq $jumpIfFalseLabel") + } + DataType.FLOAT -> { + TODO("float neq.") + } + else -> throw AssemblyError("weird operand datatype") + } + } + "<" -> { + when(dt) { + DataType.UBYTE -> translateUbyteLess(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteLess(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordLess(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordLess(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> TODO("float l.") + else -> throw AssemblyError("weird operand datatype") + } + } + "<=" -> { + when(dt) { + DataType.UBYTE -> translateUbyteLessOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteLessOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordLessOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordLessOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> TODO("float l.e.") + else -> throw AssemblyError("weird operand datatype") + } + } + ">" -> { + when(dt) { + DataType.UBYTE -> translateUbyteGreater(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteGreater(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordGreater(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordGreater(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> TODO("float g.") + else -> throw AssemblyError("weird operand datatype") + } + } + ">=" -> { + when(dt) { + DataType.UBYTE -> translateUbyteGreaterOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteGreaterOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordGreaterOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordGreaterOrEqual(left, operator, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> TODO("float g.e.") + else -> throw AssemblyError("weird operand datatype") + } + } + } + } + + private fun translateUbyteLess(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateByteLess(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUwordLess(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateWordLess(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUbyteLessOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateByteLessOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUwordLessOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateWordLessOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUbyteGreater(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateByteGreater(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUwordGreater(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateWordGreater(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUbyteGreaterOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateByteGreaterOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateUwordGreaterOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateWordGreaterOrEqual(left: Expression, operator: String, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?, jumpIfFalseLabel: String) { + TODO("Not yet implemented") + } + + private fun translateByteEquals(left: Expression, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?) { + if(rightConstVal!=null) { + if(leftConstVal!=null) { + if(rightConstVal==leftConstVal) + asmgen.out(" lda #0 | sec") + else + asmgen.out(" lda #1 | sec") + return + } else { + when(left) { + is IdentifierReference -> { + val name = asmgen.asmVariableName(left) + asmgen.out(" lda $name | cmp #${rightConstVal.number}") + return + } + // TODO optimize direct mem read here too + else -> TODO() + } + } + } + TODO("Not yet implemented") + } + + private fun translateWordEquals(left: Expression, right: Expression, leftConstVal: NumericLiteralValue?, rightConstVal: NumericLiteralValue?) { + if(rightConstVal!=null) { + if(leftConstVal!=null) { + if(rightConstVal==leftConstVal) + asmgen.out(" lda #0 | sec") + else + asmgen.out(" lda #1 | sec") + } else { + when(left) { + is IdentifierReference -> { + val name = asmgen.asmVariableName(left) + asmgen.out(""" + lda $name + cmp #<${rightConstVal.number} + bne + + lda $name+1 + cmp #>${rightConstVal.number} ++""") + return + } + // TODO optimize direct mem read here too + else -> TODO() + } + } + } + TODO("Not yet implemented") + } + private fun translateExpression(expression: FunctionCall) { val functionName = expression.target.nameInSource.last() val builtinFunc = BuiltinFunctions[functionName] @@ -100,7 +314,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge DataType.UBYTE, DataType.BYTE -> {} DataType.UWORD, DataType.WORD -> { // sign extend - asmgen.out(""" + asmgen.out(""" lda P8ESTACK_LO+1,x ora #$7f bmi + diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index d1ef548ed..3e064a223 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -249,11 +249,11 @@ internal class StatementOptimizer(private val program: Program, } override fun before(untilLoop: UntilLoop, parent: Node): Iterable { - val constvalue = untilLoop.untilCondition.constValue(program) + val constvalue = untilLoop.condition.constValue(program) if(constvalue!=null) { if(constvalue.asBooleanValue) { // always true -> keep only the statement block (if there are no break statements) - errors.warn("condition is always true", untilLoop.untilCondition.position) + errors.warn("condition is always true", untilLoop.condition.position) if(!hasBreak(untilLoop.body)) return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent)) } else { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index fadad5e4c..a0418fd2c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,9 +4,9 @@ TODO - get rid of all other TODO's in the code ;-) - line-circle-gfx examples are now a few hundred bytes larger than before (~4.0/4.1 version i think?). Why is that, can it be fixed? -- add support? example? for processing arguments to a sys call : sys 999, 1, 2, "aaa" - make it possible for array literals to not only contain compile time constants - further optimize assignment codegeneration +- further optimize expression codegeneration, most notably comparisons - implement @stack for asmsub parameters - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) diff --git a/examples/test.p8 b/examples/test.p8 index cf174ce28..3384da7da 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,15 +4,43 @@ %zeropage basicsafe -main $0900{ +main { sub start() { - ubyte x= 1 - do { - ubyte v = x + word x= 1 + + if x==10 { + x=99 + } else { + x=100 + } + + if x==10 { + ;nothing + } else { + x=100 + } + + if x==10 { + x=99 + } else { + ; nothing + } + + while 1==x { + txt.print_w(x) + txt.chrout('\n') x++ - } until v==0 + } + txt.chrout('\n') + + x=0 + do { + x++ + txt.print_w(x) + txt.chrout('\n') + } until x==10 ; @($c000) *= 99 ; TODO implement