mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
do..until condition can now refer to variables defined in the loop's inner scope.
This commit is contained in:
parent
e1d0dbed0c
commit
f5db31b8ff
@ -338,7 +338,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||||||
output("do ")
|
output("do ")
|
||||||
untilLoop.body.accept(this)
|
untilLoop.body.accept(this)
|
||||||
output(" until ")
|
output(" until ")
|
||||||
untilLoop.untilCondition.accept(this)
|
untilLoop.condition.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(returnStmt: Return) {
|
override fun visit(returnStmt: Return) {
|
||||||
|
@ -334,8 +334,8 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(untilLoop: UntilLoop) {
|
override fun visit(untilLoop: UntilLoop) {
|
||||||
if(untilLoop.untilCondition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes)
|
if(untilLoop.condition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes)
|
||||||
errors.err("condition value should be an integer type", untilLoop.untilCondition.position)
|
errors.err("condition value should be an integer type", untilLoop.condition.position)
|
||||||
super.visit(untilLoop)
|
super.visit(untilLoop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ abstract class AstWalker {
|
|||||||
|
|
||||||
fun visit(untilLoop: UntilLoop, parent: Node) {
|
fun visit(untilLoop: UntilLoop, parent: Node) {
|
||||||
track(before(untilLoop, parent), untilLoop, parent)
|
track(before(untilLoop, parent), untilLoop, parent)
|
||||||
untilLoop.untilCondition.accept(this, untilLoop)
|
untilLoop.condition.accept(this, untilLoop)
|
||||||
untilLoop.body.accept(this, untilLoop)
|
untilLoop.body.accept(this, untilLoop)
|
||||||
track(after(untilLoop, parent), untilLoop, parent)
|
track(after(untilLoop, parent), untilLoop, parent)
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ interface IAstVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visit(untilLoop: UntilLoop) {
|
fun visit(untilLoop: UntilLoop) {
|
||||||
untilLoop.untilCondition.accept(this)
|
untilLoop.condition.accept(this)
|
||||||
untilLoop.body.accept(this)
|
untilLoop.body.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,19 +815,19 @@ class RepeatLoop(var iterations: Expression?, var body: AnonymousScope, override
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UntilLoop(var body: AnonymousScope,
|
class UntilLoop(var body: AnonymousScope,
|
||||||
var untilCondition: Expression,
|
var condition: Expression,
|
||||||
override val position: Position) : Statement() {
|
override val position: Position) : Statement() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
untilCondition.linkParents(this)
|
condition.linkParents(this)
|
||||||
body.linkParents(this)
|
body.linkParents(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||||
when {
|
when {
|
||||||
node===untilCondition -> untilCondition = replacement as Expression
|
node===condition -> condition = replacement as Expression
|
||||||
node===body -> body = replacement as AnonymousScope
|
node===body -> body = replacement as AnonymousScope
|
||||||
else -> throw FatalAstException("invalid replace")
|
else -> throw FatalAstException("invalid replace")
|
||||||
}
|
}
|
||||||
|
@ -164,4 +164,34 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> {
|
||||||
|
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<IAstModification> {
|
||||||
|
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<IAstModification> {
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -845,47 +845,32 @@ $save .byte 0
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: IfStatement) {
|
private fun translate(stmt: IfStatement) {
|
||||||
when {
|
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
||||||
stmt.elsepart.containsNoCodeNorVars() -> {
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
// empty else
|
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
if (stmt.elsepart.containsNoCodeNorVars()) {
|
||||||
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
// empty else
|
||||||
val endLabel = makeLabel("if_end")
|
val endLabel = makeLabel("if_end")
|
||||||
out(" beq $endLabel")
|
expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, endLabel)
|
||||||
translate(stmt.truepart)
|
translate(stmt.truepart)
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
}
|
}
|
||||||
stmt.truepart.containsNoCodeNorVars() -> {
|
else {
|
||||||
// empty true part
|
// both true and else parts
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
val elseLabel = makeLabel("if_else")
|
||||||
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
val endLabel = makeLabel("if_end")
|
||||||
val endLabel = makeLabel("if_end")
|
expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, elseLabel)
|
||||||
out(" bne $endLabel")
|
translate(stmt.truepart)
|
||||||
translate(stmt.elsepart)
|
out(" jmp $endLabel")
|
||||||
out(endLabel)
|
out(elseLabel)
|
||||||
}
|
translate(stmt.elsepart)
|
||||||
else -> {
|
out(endLabel)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateTestStack(dataType: DataType) {
|
private fun checkBooleanExpression(condition: Expression) {
|
||||||
when(dataType) {
|
if(condition !is BinaryExpression || condition.operator !in comparisonOperators)
|
||||||
in ByteDatatypes -> out(" inx | lda P8ESTACK_LO,x")
|
throw AssemblyError("expected boolean expression $condition")
|
||||||
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 translate(stmt: RepeatLoop) {
|
private fun translate(stmt: RepeatLoop) {
|
||||||
@ -1004,25 +989,13 @@ $counterVar .byte 0""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: WhileLoop) {
|
private fun translate(stmt: WhileLoop) {
|
||||||
|
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
||||||
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
val whileLabel = makeLabel("while")
|
val whileLabel = makeLabel("while")
|
||||||
val endLabel = makeLabel("whileend")
|
val endLabel = makeLabel("whileend")
|
||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
out(whileLabel)
|
out(whileLabel)
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, endLabel)
|
||||||
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
|
|
||||||
+ """)
|
|
||||||
}
|
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
out(" jmp $whileLabel")
|
out(" jmp $whileLabel")
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
@ -1030,26 +1003,14 @@ $counterVar .byte 0""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: UntilLoop) {
|
private fun translate(stmt: UntilLoop) {
|
||||||
|
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
||||||
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
val repeatLabel = makeLabel("repeat")
|
val repeatLabel = makeLabel("repeat")
|
||||||
val endLabel = makeLabel("repeatend")
|
val endLabel = makeLabel("repeatend")
|
||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
out(repeatLabel)
|
out(repeatLabel)
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
expressionsAsmGen.translateExpression(stmt.untilCondition)
|
expressionsAsmGen.translateComparisonExpressionWithJumpIfFalse(booleanCondition, repeatLabel)
|
||||||
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
|
|
||||||
+ """)
|
|
||||||
}
|
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
loopEndLabels.pop()
|
loopEndLabels.pop()
|
||||||
}
|
}
|
||||||
|
@ -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: <constvalue> <comparison> 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) {
|
private fun translateExpression(expression: FunctionCall) {
|
||||||
val functionName = expression.target.nameInSource.last()
|
val functionName = expression.target.nameInSource.last()
|
||||||
val builtinFunc = BuiltinFunctions[functionName]
|
val builtinFunc = BuiltinFunctions[functionName]
|
||||||
@ -100,7 +314,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
DataType.UBYTE, DataType.BYTE -> {}
|
DataType.UBYTE, DataType.BYTE -> {}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
// sign extend
|
// sign extend
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
ora #$7f
|
ora #$7f
|
||||||
bmi +
|
bmi +
|
||||||
|
@ -249,11 +249,11 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun before(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> {
|
override fun before(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> {
|
||||||
val constvalue = untilLoop.untilCondition.constValue(program)
|
val constvalue = untilLoop.condition.constValue(program)
|
||||||
if(constvalue!=null) {
|
if(constvalue!=null) {
|
||||||
if(constvalue.asBooleanValue) {
|
if(constvalue.asBooleanValue) {
|
||||||
// always true -> keep only the statement block (if there are no break statements)
|
// 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))
|
if(!hasBreak(untilLoop.body))
|
||||||
return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent))
|
return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent))
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,9 +4,9 @@ TODO
|
|||||||
|
|
||||||
- get rid of all other TODO's in the code ;-)
|
- 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?
|
- 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
|
- make it possible for array literals to not only contain compile time constants
|
||||||
- further optimize assignment codegeneration
|
- further optimize assignment codegeneration
|
||||||
|
- further optimize expression codegeneration, most notably comparisons
|
||||||
- implement @stack for asmsub parameters
|
- 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 '_'
|
- 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)
|
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
||||||
|
@ -4,15 +4,43 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
main $0900{
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
ubyte x= 1
|
word x= 1
|
||||||
do {
|
|
||||||
ubyte v = x
|
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++
|
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
|
; @($c000) *= 99 ; TODO implement
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user