added transform routine for expr -> RPN

This commit is contained in:
Irmen de Jong 2023-03-16 02:27:30 +01:00
parent 7fea0c124a
commit 8ffca93cd5
15 changed files with 175 additions and 127 deletions

View File

@ -64,6 +64,40 @@ class PtProgram(
fun entrypoint(): PtSub? = fun entrypoint(): PtSub? =
allBlocks().firstOrNull { it.name == "main" }?.children?.firstOrNull { it is PtSub && it.name == "start" } as PtSub? allBlocks().firstOrNull { it.name == "main" }?.children?.firstOrNull { it is PtSub && it.name == "start" } as PtSub?
// If the code generator wants, it can transform binary expression nodes into flat RPN nodes.
// This will destroy the original binaryexpression nodes!
fun transformBinExprToRPN() {
fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn {
fun makeRpn(expr: PtExpression): PtRpn {
val rpn = PtRpn(expr.type, expr.position)
rpn.addRpnNode(expr)
return rpn
}
val rpn = PtRpn(originalExpr.type, position)
rpn.addRpnNode(makeRpn(originalExpr.left))
rpn.addRpnNode(makeRpn(originalExpr.right))
rpn.addRpnNode(PtRpnOperator(originalExpr.operator, originalExpr.type, originalExpr.left.type, originalExpr.right.type, position))
return rpn
}
fun transformBinExprToRPN(node: PtNode, parent: PtNode) {
if(node is PtBinaryExpression) {
val rpn = transformToRPN(node)
val idx = parent.children.indexOf(node)
rpn.parent = parent
parent.children[idx] = rpn
}
node.children.forEach {child ->
transformBinExprToRPN(child, node)
}
}
children.forEach { transformBinExprToRPN(it, this) }
}
} }

View File

@ -27,7 +27,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
return when(this) { return when(this) {
is PtAddressOf -> other is PtAddressOf && other.type==type && other.identifier isSameAs identifier is PtAddressOf -> other is PtAddressOf && other.type==type && other.identifier isSameAs identifier
is PtArrayIndexer -> other is PtArrayIndexer && other.type==type && other.variable isSameAs variable && other.index isSameAs index is PtArrayIndexer -> other is PtArrayIndexer && other.type==type && other.variable isSameAs variable && other.index isSameAs index
is PtBinaryExpressionObsoleteUsePtRpn -> other is PtBinaryExpressionObsoleteUsePtRpn && other.left isSameAs left && other.right isSameAs right is PtBinaryExpression -> other is PtBinaryExpression && other.left isSameAs left && other.right isSameAs right
is PtRpn -> other is PtRpn && this.isSame(other) is PtRpn -> other is PtRpn && this.isSame(other)
is PtContainmentCheck -> other is PtContainmentCheck && other.type==type && other.element isSameAs element && other.iterable isSameAs iterable is PtContainmentCheck -> other is PtContainmentCheck && other.type==type && other.element isSameAs element && other.iterable isSameAs iterable
is PtIdentifier -> other is PtIdentifier && other.type==type && other.name==name is PtIdentifier -> other is PtIdentifier && other.type==type && other.name==name
@ -63,7 +63,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
is PtAddressOf -> true is PtAddressOf -> true
is PtArray -> true is PtArray -> true
is PtArrayIndexer -> index is PtNumber || index is PtIdentifier is PtArrayIndexer -> index is PtNumber || index is PtIdentifier
is PtBinaryExpressionObsoleteUsePtRpn -> false is PtBinaryExpression -> false
is PtRpn -> false is PtRpn -> false
is PtBuiltinFunctionCall -> name in arrayOf("msb", "lsb", "peek", "peekw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") is PtBuiltinFunctionCall -> name in arrayOf("msb", "lsb", "peek", "peekw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd")
is PtContainmentCheck -> false is PtContainmentCheck -> false
@ -152,7 +152,7 @@ class PtBuiltinFunctionCall(val name: String,
} }
class PtBinaryExpressionObsoleteUsePtRpn(val operator: String, type: DataType, position: Position): PtExpression(type, position) { class PtBinaryExpression(val operator: String, type: DataType, position: Position): PtExpression(type, position) {
// note: "and", "or", "xor" do not occur anymore as operators. They've been replaced int the ast by their bitwise versions &, |, ^. // note: "and", "or", "xor" do not occur anymore as operators. They've been replaced int the ast by their bitwise versions &, |, ^.
val left: PtExpression val left: PtExpression
get() = children[0] as PtExpression get() = children[0] as PtExpression
@ -163,13 +163,21 @@ class PtBinaryExpressionObsoleteUsePtRpn(val operator: String, type: DataType, p
class PtRpn(type: DataType, position: Position): PtExpression(type, position) { class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
// contains only PtExpression (not PtRpn!) and PtRpnOperator nodes // contains only PtExpression (not PtRpn!) and PtRpnOperator nodes
// not created directly by the compiler for now, if code generators prefer this over PtBinaryExpression,
// they have to transform the ast themselves first using the utility routine on PtProgram for it.
operator fun plusAssign(node: PtNode) { fun addRpnNode(node: PtNode) {
require(node is PtRpnOperator || node is PtExpression) require(node is PtRpnOperator || node is PtExpression)
if(node is PtRpn) if(node is PtRpn) {
children.addAll(node.children) node.children.forEach {
else children += it
it.parent = this
}
}
else {
children += node children += node
node.parent = this
}
} }
fun print() { fun print() {
@ -259,9 +267,16 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
} }
class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) { class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) {
init { // init {
require(type==operand1Type && type==operand2Type) // TODO if this is always true, can remove operand1 and 2 types again. // require(operand1Type equalsSize operand2Type) {
} // "operator $operator : operand1 and 2 types aren't equal sizes: $operand1Type $operand2Type"
// }
// if(operator !in ComparisonOperators) {
// require(type equalsSize operand1Type && type equalsSize operand2Type) {
// "operator $operator : type $type size not equal to operand1 and 2 types: $operand1Type $operand2Type"
// }
// }
// }
} }

View File

@ -18,7 +18,7 @@ fun printAst(root: PtNode, output: (text: String) -> Unit) {
is PtAddressOf -> "&" is PtAddressOf -> "&"
is PtArray -> "array len=${node.children.size} ${type(node.type)}" is PtArray -> "array len=${node.children.size} ${type(node.type)}"
is PtArrayIndexer -> "<arrayindexer> ${type(node.type)}" is PtArrayIndexer -> "<arrayindexer> ${type(node.type)}"
is PtBinaryExpressionObsoleteUsePtRpn -> "<expr> ${node.operator} ${type(node.type)}" is PtBinaryExpression -> "<expr> ${node.operator} ${type(node.type)}"
is PtRpn -> "<rpnexpr>" is PtRpn -> "<rpnexpr>"
is PtRpnOperator -> node.operator is PtRpnOperator -> node.operator
is PtBuiltinFunctionCall -> { is PtBuiltinFunctionCall -> {

View File

@ -100,8 +100,8 @@ class PtForLoop(position: Position) : PtNode(position) {
class PtIfElse(position: Position) : PtNode(position) { class PtIfElse(position: Position) : PtNode(position) {
val condition: PtBinaryExpressionObsoleteUsePtRpn val condition: PtNode
get() = children[0] as PtBinaryExpressionObsoleteUsePtRpn get() = children[0] as PtNode
val ifScope: PtNodeGroup val ifScope: PtNodeGroup
get() = children[1] as PtNodeGroup get() = children[1] as PtNodeGroup
val elseScope: PtNodeGroup val elseScope: PtNodeGroup

View File

@ -21,6 +21,9 @@ class AsmGen6502: ICodeGeneratorBackend {
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this:
// TODO program.transformBinExprToRPN()
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors) val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
return asmgen.compileToAssembly() return asmgen.compileToAssembly()
} }
@ -544,16 +547,16 @@ class AsmGen6502Internal (
} }
private fun translate(stmt: PtIfElse) { private fun translate(stmt: PtIfElse) {
requireComparisonExpression(stmt.condition) // IfStatement: condition must be of form 'x <comparison> <value>' val condition = stmt.condition as PtBinaryExpression
val booleanCondition = stmt.condition requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
if (stmt.elseScope.children.isEmpty()) { if (stmt.elseScope.children.isEmpty()) {
val jump = stmt.ifScope.children.singleOrNull() val jump = stmt.ifScope.children.singleOrNull()
if(jump is PtJump) { if(jump is PtJump) {
translateCompareAndJumpIfTrue(booleanCondition, jump) translateCompareAndJumpIfTrue(condition, jump)
} else { } else {
val endLabel = makeLabel("if_end") val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(booleanCondition, endLabel) translateCompareAndJumpIfFalse(condition, endLabel)
translate(stmt.ifScope) translate(stmt.ifScope)
out(endLabel) out(endLabel)
} }
@ -562,7 +565,7 @@ class AsmGen6502Internal (
// both true and else parts // both true and else parts
val elseLabel = makeLabel("if_else") val elseLabel = makeLabel("if_else")
val endLabel = makeLabel("if_end") val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(booleanCondition, elseLabel) translateCompareAndJumpIfFalse(condition, elseLabel)
translate(stmt.ifScope) translate(stmt.ifScope)
jmp(endLabel) jmp(endLabel)
out(elseLabel) out(elseLabel)
@ -572,7 +575,7 @@ class AsmGen6502Internal (
} }
private fun requireComparisonExpression(condition: PtExpression) { private fun requireComparisonExpression(condition: PtExpression) {
if(condition !is PtBinaryExpressionObsoleteUsePtRpn || condition.operator !in ComparisonOperators) if(condition !is PtBinaryExpression || condition.operator !in ComparisonOperators)
throw AssemblyError("expected boolean comparison expression $condition") throw AssemblyError("expected boolean comparison expression $condition")
} }
@ -977,7 +980,7 @@ $repeatLabel lda $counterVar
} }
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? { internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
if(pointerOffsetExpr is PtBinaryExpressionObsoleteUsePtRpn && pointerOffsetExpr.operator=="+") { if(pointerOffsetExpr is PtBinaryExpression && pointerOffsetExpr.operator=="+") {
val leftDt = pointerOffsetExpr.left.type val leftDt = pointerOffsetExpr.left.type
val rightDt = pointerOffsetExpr.left.type val rightDt = pointerOffsetExpr.left.type
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE) if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
@ -1003,7 +1006,7 @@ $repeatLabel lda $counterVar
return null return null
} }
internal fun tryOptimizedPointerAccessWithA(expr: PtBinaryExpressionObsoleteUsePtRpn, write: Boolean): Boolean { internal fun tryOptimizedPointerAccessWithA(expr: PtBinaryExpression, write: Boolean): Boolean {
// optimize pointer,indexregister if possible // optimize pointer,indexregister if possible
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean { fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
@ -1095,7 +1098,7 @@ $repeatLabel lda $counterVar
return node.definingSub()?.parameters?.singleOrNull { it.name===name } return node.definingSub()?.parameters?.singleOrNull { it.name===name }
} }
private fun translateCompareAndJumpIfTrue(expr: PtBinaryExpressionObsoleteUsePtRpn, jump: PtJump) { private fun translateCompareAndJumpIfTrue(expr: PtBinaryExpression, jump: PtJump) {
if(expr.operator !in ComparisonOperators) if(expr.operator !in ComparisonOperators)
throw AssemblyError("must be comparison expression") throw AssemblyError("must be comparison expression")
@ -1121,7 +1124,7 @@ $repeatLabel lda $counterVar
} }
} }
private fun translateCompareAndJumpIfFalse(expr: PtBinaryExpressionObsoleteUsePtRpn, jumpIfFalseLabel: String) { private fun translateCompareAndJumpIfFalse(expr: PtBinaryExpression, jumpIfFalseLabel: String) {
val left = expr.left val left = expr.left
val right = expr.right val right = expr.right
val operator = expr.operator val operator = expr.operator
@ -2833,8 +2836,8 @@ $repeatLabel lda $counterVar
if(pushResultOnEstack) if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex") out(" sta P8ESTACK_LO,x | dex")
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(tryOptimizedPointerAccessWithA(expr.address as PtBinaryExpressionObsoleteUsePtRpn, false)) { if(tryOptimizedPointerAccessWithA(expr.address as PtBinaryExpression, false)) {
if(pushResultOnEstack) if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex") out(" sta P8ESTACK_LO,x | dex")
} else { } else {

View File

@ -664,7 +664,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
is PtRpn -> { is PtRpn -> {
TODO("pokeW for RPN $addrExpr") TODO("pokeW for RPN $addrExpr")
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) { if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) {
val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier) val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier)
if(asmgen.isZpVar(addrExpr.left as PtIdentifier)) { if(asmgen.isZpVar(addrExpr.left as PtIdentifier)) {
@ -726,7 +726,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
is PtRpn -> { is PtRpn -> {
TODO("peekW for RPN $addrExpr") TODO("peekW for RPN $addrExpr")
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) { if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) {
val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier) val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier)
if(asmgen.isZpVar(addrExpr.left as PtIdentifier)) { if(asmgen.isZpVar(addrExpr.left as PtIdentifier)) {

View File

@ -24,7 +24,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
when(expression) { when(expression) {
is PtPrefix -> translateExpression(expression) is PtPrefix -> translateExpression(expression)
is PtBinaryExpressionObsoleteUsePtRpn -> translateExpression(expression) is PtBinaryExpression -> translateExpression(expression)
is PtRpn -> translateExpression(expression) is PtRpn -> translateExpression(expression)
is PtArrayIndexer -> translateExpression(expression) is PtArrayIndexer -> translateExpression(expression)
is PtTypeCast -> translateExpression(expression) is PtTypeCast -> translateExpression(expression)
@ -244,7 +244,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
TODO("translate RPN $expr") TODO("translate RPN $expr")
} }
private fun translateExpression(expr: PtBinaryExpressionObsoleteUsePtRpn) { private fun translateExpression(expr: PtBinaryExpression) {
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
val leftDt = expr.left.type val leftDt = expr.left.type
val rightDt = expr.right.type val rightDt = expr.right.type

View File

@ -144,8 +144,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
is PtRpn -> { is PtRpn -> {
TODO("translate RPN ${value.address}") TODO("translate RPN ${value.address}")
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpressionObsoleteUsePtRpn, false)) { if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpression, false)) {
assignRegisterByte(assign.target, CpuRegister.A) assignRegisterByte(assign.target, CpuRegister.A)
} else { } else {
assignViaExprEval(value.address) assignViaExprEval(value.address)
@ -297,7 +297,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
containmentCheckIntoA(value) containmentCheckIntoA(value)
assignRegisterByte(assign.target, CpuRegister.A) assignRegisterByte(assign.target, CpuRegister.A)
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(!attemptAssignOptimizedBinexpr(value, assign)) { if(!attemptAssignOptimizedBinexpr(value, assign)) {
// All remaining binary expressions just evaluate via the stack for now. // All remaining binary expressions just evaluate via the stack for now.
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
@ -345,7 +345,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
} }
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpressionObsoleteUsePtRpn, assign: AsmAssignment): Boolean { private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
if(expr.operator in ComparisonOperators) { if(expr.operator in ComparisonOperators) {
if(expr.right.asConstInteger() == 0) { if(expr.right.asConstInteger() == 0) {
if(expr.operator == "==" || expr.operator=="!=") { if(expr.operator == "==" || expr.operator=="!=") {
@ -367,7 +367,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignTrue.add(assignment) assignTrue.add(assignment)
val assignFalse = PtNodeGroup() val assignFalse = PtNodeGroup()
val ifelse = PtIfElse(assign.position) val ifelse = PtIfElse(assign.position)
val exprClone = PtBinaryExpressionObsoleteUsePtRpn(expr.operator, expr.type, expr.position) val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position)
expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone
ifelse.add(exprClone) ifelse.add(exprClone)
ifelse.add(assignTrue) ifelse.add(assignTrue)
@ -727,7 +727,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignRegisterpairWord(target, RegisterOrPair.AY) assignRegisterpairWord(target, RegisterOrPair.AY)
} }
private fun attemptAssignToByteCompareZero(expr: PtBinaryExpressionObsoleteUsePtRpn, assign: AsmAssignment): Boolean { private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
when (expr.operator) { when (expr.operator) {
"==" -> { "==" -> {
when(val dt = expr.left.type) { when(val dt = expr.left.type) {
@ -909,8 +909,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
is PtRpn -> { is PtRpn -> {
TODO("translate RPN ${value.address}") TODO("translate RPN ${value.address}")
} }
is PtBinaryExpressionObsoleteUsePtRpn -> { is PtBinaryExpression -> {
if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpressionObsoleteUsePtRpn, false)) { if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpression, false)) {
asmgen.out(" ldy #0") asmgen.out(" ldy #0")
assignRegisterpairWord(target, RegisterOrPair.AY) assignRegisterpairWord(target, RegisterOrPair.AY)
} else { } else {
@ -2833,7 +2833,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
addressExpr is PtRpn -> { addressExpr is PtRpn -> {
TODO("translate RPN $addressExpr") TODO("translate RPN $addressExpr")
} }
addressExpr is PtBinaryExpressionObsoleteUsePtRpn -> { addressExpr is PtBinaryExpression -> {
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true)) if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true))
storeViaExprEval() storeViaExprEval()
} }

View File

@ -16,6 +16,10 @@ class ExperiCodeGen: ICodeGeneratorBackend {
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this:
// program.transformBinExprToRPN()
// you could write a code generator directly on the PtProgram AST, // you could write a code generator directly on the PtProgram AST,
// but you can also use the Intermediate Representation to build a codegen on: // but you can also use the Intermediate Representation to build a codegen on:
val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irCodeGen = IRCodeGen(program, symbolTable, options, errors)

View File

@ -92,7 +92,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
value.add(origAssign.value) value.add(origAssign.value)
} else { } else {
require(origAssign.operator.endsWith('=')) require(origAssign.operator.endsWith('='))
value = PtBinaryExpressionObsoleteUsePtRpn(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position) value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
val left: PtExpression = origAssign.target.children.single() as PtExpression val left: PtExpression = origAssign.target.children.single() as PtExpression
value.add(left) value.add(left)
value.add(origAssign.value) value.add(origAssign.value)
@ -262,7 +262,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val tr = if(itemsize==1) { val tr = if(itemsize==1) {
expressionEval.translateExpression(array.index) expressionEval.translateExpression(array.index)
} else { } else {
val mult = PtBinaryExpressionObsoleteUsePtRpn("*", DataType.UBYTE, array.position) val mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
mult.children += array.index mult.children += array.index
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position) mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
expressionEval.translateExpression(mult) expressionEval.translateExpression(mult)

View File

@ -92,7 +92,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
is PtTypeCast -> translate(expr) is PtTypeCast -> translate(expr)
is PtPrefix -> translate(expr) is PtPrefix -> translate(expr)
is PtArrayIndexer -> translate(expr) is PtArrayIndexer -> translate(expr)
is PtBinaryExpressionObsoleteUsePtRpn -> translate(expr) is PtBinaryExpression -> translate(expr)
is PtRpn -> translate(expr) is PtRpn -> translate(expr)
is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr) is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr)
is PtFunctionCall -> translate(expr) is PtFunctionCall -> translate(expr)
@ -320,7 +320,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
TODO("translate RPN expression $rpn") TODO("translate RPN expression $rpn")
} }
private fun translate(binExpr: PtBinaryExpressionObsoleteUsePtRpn): ExpressionCodeResult { private fun translate(binExpr: PtBinaryExpression): ExpressionCodeResult {
val vmDt = codeGen.irType(binExpr.left.type) val vmDt = codeGen.irType(binExpr.left.type)
val signed = binExpr.left.type in SignedDatatypes val signed = binExpr.left.type in SignedDatatypes
return when(binExpr.operator) { return when(binExpr.operator) {
@ -435,7 +435,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
private fun operatorGreaterThan( private fun operatorGreaterThan(
binExpr: PtBinaryExpressionObsoleteUsePtRpn, binExpr: PtBinaryExpression,
vmDt: IRDataType, vmDt: IRDataType,
signed: Boolean, signed: Boolean,
greaterEquals: Boolean greaterEquals: Boolean
@ -491,7 +491,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
private fun operatorLessThan( private fun operatorLessThan(
binExpr: PtBinaryExpressionObsoleteUsePtRpn, binExpr: PtBinaryExpression,
vmDt: IRDataType, vmDt: IRDataType,
signed: Boolean, signed: Boolean,
lessEquals: Boolean lessEquals: Boolean
@ -546,7 +546,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorEquals(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType, notEquals: Boolean): ExpressionCodeResult { private fun operatorEquals(binExpr: PtBinaryExpression, vmDt: IRDataType, notEquals: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
if(vmDt==IRDataType.FLOAT) { if(vmDt==IRDataType.FLOAT) {
val leftTr = translateExpression(binExpr.left) val leftTr = translateExpression(binExpr.left)
@ -601,7 +601,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorShiftRight(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult { private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(codeGen.isOne(binExpr.right)) { return if(codeGen.isOne(binExpr.right)) {
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
@ -620,7 +620,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorShiftLeft(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(codeGen.isOne(binExpr.right)){ return if(codeGen.isOne(binExpr.right)){
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
@ -637,7 +637,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorXor(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorXor(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(binExpr.right is PtNumber) { return if(binExpr.right is PtNumber) {
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
@ -654,7 +654,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorAnd(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(binExpr.right is PtNumber) { return if(binExpr.right is PtNumber) {
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
@ -671,7 +671,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorOr(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorOr(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(binExpr.right is PtNumber) { return if(binExpr.right is PtNumber) {
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
@ -688,7 +688,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorModulo(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported ${binExpr.position}"} require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported ${binExpr.position}"}
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
return if(binExpr.right is PtNumber) { return if(binExpr.right is PtNumber) {
@ -706,7 +706,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorDivide(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult { private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val constFactorRight = binExpr.right as? PtNumber val constFactorRight = binExpr.right as? PtNumber
if(vmDt==IRDataType.FLOAT) { if(vmDt==IRDataType.FLOAT) {
@ -761,7 +761,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorMultiply(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val constFactorLeft = binExpr.left as? PtNumber val constFactorLeft = binExpr.left as? PtNumber
val constFactorRight = binExpr.right as? PtNumber val constFactorRight = binExpr.right as? PtNumber
@ -810,7 +810,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorMinus(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
if(vmDt==IRDataType.FLOAT) { if(vmDt==IRDataType.FLOAT) {
if((binExpr.right as? PtNumber)?.number==1.0) { if((binExpr.right as? PtNumber)?.number==1.0) {
@ -859,7 +859,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} }
private fun operatorPlus(binExpr: PtBinaryExpressionObsoleteUsePtRpn, vmDt: IRDataType): ExpressionCodeResult { private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
if(vmDt==IRDataType.FLOAT) { if(vmDt==IRDataType.FLOAT) {
if((binExpr.left as? PtNumber)?.number==1.0) { if((binExpr.left as? PtNumber)?.number==1.0) {

View File

@ -268,7 +268,7 @@ class IRCodeGen(
is PtMemoryByte, is PtMemoryByte,
is PtProgram, is PtProgram,
is PtArrayIndexer, is PtArrayIndexer,
is PtBinaryExpressionObsoleteUsePtRpn, is PtBinaryExpression,
is PtRpn, is PtRpn,
is PtRpnOperator, is PtRpnOperator,
is PtIdentifier, is PtIdentifier,
@ -898,30 +898,35 @@ class IRCodeGen(
private fun translate(ifElse: PtIfElse): IRCodeChunks { private fun translate(ifElse: PtIfElse): IRCodeChunks {
val condition = ifElse.condition val condition = ifElse.condition
if(condition.operator !in ComparisonOperators) if(condition is PtBinaryExpression) {
throw AssemblyError("if condition should only be a binary comparison expression") if(condition.operator !in ComparisonOperators)
throw AssemblyError("if condition should only be a binary comparison expression")
val signed = condition.left.type in SignedDatatypes val signed = condition.left.type in SignedDatatypes
val irDtLeft = irType(condition.left.type) val irDtLeft = irType(condition.left.type)
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
return when { return when {
goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed) goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed)
constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed) constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed)
else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed) else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed)
}
} else {
TODO("weird condition node: $condition")
} }
} }
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> { private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val condition = ifElse.condition as PtBinaryExpression
if(irDtLeft==IRDataType.FLOAT) { if(irDtLeft==IRDataType.FLOAT) {
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, -1, leftTr.resultFpReg) addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = expressionEval.translateExpression(ifElse.condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg) addToResult(result, rightTr, -1, rightTr.resultFpReg)
result += IRCodeChunk(null,null).also { result += IRCodeChunk(null,null).also {
val compResultReg = registers.nextFree() val compResultReg = registers.nextFree()
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
val gotoOpcode = when (ifElse.condition.operator) { val gotoOpcode = when (condition.operator) {
"==" -> Opcode.BZ "==" -> Opcode.BZ
"!=" -> Opcode.BNZ "!=" -> Opcode.BNZ
"<" -> Opcode.BLEZS "<" -> Opcode.BLEZS
@ -939,7 +944,7 @@ class IRCodeGen(
} }
return result return result
} else { } else {
val rightConst = ifElse.condition.right.asConstInteger() val rightConst = condition.right.asConstInteger()
return if(rightConst==0) return if(rightConst==0)
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto) ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
else { else {
@ -955,9 +960,10 @@ class IRCodeGen(
irDtLeft: IRDataType, irDtLeft: IRDataType,
goto: PtJump goto: PtJump
): MutableList<IRCodeChunkBase> { ): MutableList<IRCodeChunkBase> {
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val condition = ifElse.condition as PtBinaryExpression
val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val opcode = when (ifElse.condition.operator) { val opcode = when (condition.operator) {
"==" -> Opcode.BZ "==" -> Opcode.BZ
"!=" -> Opcode.BNZ "!=" -> Opcode.BNZ
"<" -> if (signed) Opcode.BLZS else throw AssemblyError("unsigned < 0 shouldn't occur in codegen") "<" -> if (signed) Opcode.BLZS else throw AssemblyError("unsigned < 0 shouldn't occur in codegen")
@ -982,14 +988,15 @@ class IRCodeGen(
irDtLeft: IRDataType, irDtLeft: IRDataType,
goto: PtJump goto: PtJump
): MutableList<IRCodeChunkBase> { ): MutableList<IRCodeChunkBase> {
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val condition = ifElse.condition as PtBinaryExpression
val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val rightTr = expressionEval.translateExpression(ifElse.condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, rightTr.resultReg, -1) addToResult(result, rightTr, rightTr.resultReg, -1)
val opcode: Opcode val opcode: Opcode
val firstReg: Int val firstReg: Int
val secondReg: Int val secondReg: Int
when (ifElse.condition.operator) { when (condition.operator) {
"==" -> { "==" -> {
opcode = Opcode.BEQ opcode = Opcode.BEQ
firstReg = leftTr.resultReg firstReg = leftTr.resultReg
@ -1038,17 +1045,18 @@ class IRCodeGen(
val elseBranch: Opcode val elseBranch: Opcode
val compResultReg: Int val compResultReg: Int
val branchDt: IRDataType val branchDt: IRDataType
val condition = ifElse.condition as PtBinaryExpression
if(irDtLeft==IRDataType.FLOAT) { if(irDtLeft==IRDataType.FLOAT) {
branchDt = IRDataType.BYTE branchDt = IRDataType.BYTE
compResultReg = registers.nextFree() compResultReg = registers.nextFree()
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, -1, leftTr.resultFpReg) addToResult(result, leftTr, -1, leftTr.resultFpReg)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
val rightFpReg = registers.nextFreeFloat() val rightFpReg = registers.nextFreeFloat()
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, fpValue = 0f) it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, fpValue = 0f)
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg)
} }
elseBranch = when (ifElse.condition.operator) { elseBranch = when (condition.operator) {
"==" -> Opcode.BNZ "==" -> Opcode.BNZ
"!=" -> Opcode.BZ "!=" -> Opcode.BZ
"<" -> Opcode.BGEZS "<" -> Opcode.BGEZS
@ -1060,10 +1068,10 @@ class IRCodeGen(
} else { } else {
// integer comparisons // integer comparisons
branchDt = irDtLeft branchDt = irDtLeft
val tr = expressionEval.translateExpression(ifElse.condition.left) val tr = expressionEval.translateExpression(condition.left)
compResultReg = tr.resultReg compResultReg = tr.resultReg
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
elseBranch = when (ifElse.condition.operator) { elseBranch = when (condition.operator) {
"==" -> Opcode.BNZ "==" -> Opcode.BNZ
"!=" -> Opcode.BZ "!=" -> Opcode.BZ
"<" -> if (signed) Opcode.BGEZS else throw AssemblyError("unsigned < 0 shouldn't occur in codegen") "<" -> if (signed) Opcode.BGEZS else throw AssemblyError("unsigned < 0 shouldn't occur in codegen")
@ -1100,14 +1108,15 @@ class IRCodeGen(
val elseBranchFirstReg: Int val elseBranchFirstReg: Int
val elseBranchSecondReg: Int val elseBranchSecondReg: Int
val branchDt: IRDataType val branchDt: IRDataType
val condition = ifElse.condition as PtBinaryExpression
if(irDtLeft==IRDataType.FLOAT) { if(irDtLeft==IRDataType.FLOAT) {
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, -1, leftTr.resultFpReg) addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = expressionEval.translateExpression(ifElse.condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg) addToResult(result, rightTr, -1, rightTr.resultFpReg)
val compResultReg = registers.nextFree() val compResultReg = registers.nextFree()
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
val elseBranch = when (ifElse.condition.operator) { val elseBranch = when (condition.operator) {
"==" -> Opcode.BNZ "==" -> Opcode.BNZ
"!=" -> Opcode.BZ "!=" -> Opcode.BZ
"<" -> Opcode.BGEZS "<" -> Opcode.BGEZS
@ -1135,11 +1144,11 @@ class IRCodeGen(
} else { } else {
// integer comparisons // integer comparisons
branchDt = irDtLeft branchDt = irDtLeft
val leftTr = expressionEval.translateExpression(ifElse.condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val rightTr = expressionEval.translateExpression(ifElse.condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, rightTr.resultReg, -1) addToResult(result, rightTr, rightTr.resultReg, -1)
when (ifElse.condition.operator) { when (condition.operator) {
"==" -> { "==" -> {
elseBranchOpcode = Opcode.BNE elseBranchOpcode = Opcode.BNE
elseBranchFirstReg = leftTr.resultReg elseBranchFirstReg = leftTr.resultReg

View File

@ -17,6 +17,8 @@ class VmCodeGen: ICodeGeneratorBackend {
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this:
// program.transformBinExprToRPN()
val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
val irProgram = irCodeGen.generate() val irProgram = irCodeGen.generate()
return VmAssemblyProgram(irProgram.name, irProgram) return VmAssemblyProgram(irProgram.name, irProgram)

View File

@ -122,7 +122,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.UBYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.UBYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp1.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -130,7 +130,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn("!=", DataType.UBYTE, Position.DUMMY) val cmp2 = PtBinaryExpression("!=", DataType.UBYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp2.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)
@ -138,7 +138,7 @@ class TestVmCodeGen: FunSpec({
if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if2) sub.add(if2)
val if3 = PtIfElse(Position.DUMMY) val if3 = PtIfElse(Position.DUMMY)
val cmp3 = PtBinaryExpressionObsoleteUsePtRpn("<", DataType.UBYTE, Position.DUMMY) val cmp3 = PtBinaryExpression("<", DataType.UBYTE, Position.DUMMY)
cmp3.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp3.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp3.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY)) cmp3.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY))
if3.add(cmp3) if3.add(cmp3)
@ -146,7 +146,7 @@ class TestVmCodeGen: FunSpec({
if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if3) sub.add(if3)
val if4 = PtIfElse(Position.DUMMY) val if4 = PtIfElse(Position.DUMMY)
val cmp4 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.UBYTE, Position.DUMMY) val cmp4 = PtBinaryExpression(">", DataType.UBYTE, Position.DUMMY)
cmp4.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp4.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp4.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY)) cmp4.add(PtNumber(DataType.FLOAT, 0.0, Position.DUMMY))
if4.add(cmp4) if4.add(cmp4)
@ -185,7 +185,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.UBYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.UBYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp1.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -193,7 +193,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn("!=", DataType.UBYTE, Position.DUMMY) val cmp2 = PtBinaryExpression("!=", DataType.UBYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp2.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)
@ -201,7 +201,7 @@ class TestVmCodeGen: FunSpec({
if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if2) sub.add(if2)
val if3 = PtIfElse(Position.DUMMY) val if3 = PtIfElse(Position.DUMMY)
val cmp3 = PtBinaryExpressionObsoleteUsePtRpn("<", DataType.UBYTE, Position.DUMMY) val cmp3 = PtBinaryExpression("<", DataType.UBYTE, Position.DUMMY)
cmp3.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp3.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp3.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp3.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if3.add(cmp3) if3.add(cmp3)
@ -209,7 +209,7 @@ class TestVmCodeGen: FunSpec({
if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if3) sub.add(if3)
val if4 = PtIfElse(Position.DUMMY) val if4 = PtIfElse(Position.DUMMY)
val cmp4 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.UBYTE, Position.DUMMY) val cmp4 = PtBinaryExpression(">", DataType.UBYTE, Position.DUMMY)
cmp4.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp4.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp4.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp4.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if4.add(cmp4) if4.add(cmp4)
@ -244,7 +244,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.UBYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.UBYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp1.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -252,7 +252,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup()) if1.add(PtNodeGroup())
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.UBYTE, Position.DUMMY) val cmp2 = PtBinaryExpression(">", DataType.UBYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.f1", DataType.FLOAT, Position.DUMMY))
cmp2.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.FLOAT, 42.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)
@ -291,7 +291,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.BYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.BYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp1.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -299,7 +299,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn("!=", DataType.BYTE, Position.DUMMY) val cmp2 = PtBinaryExpression("!=", DataType.BYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp2.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)
@ -307,7 +307,7 @@ class TestVmCodeGen: FunSpec({
if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if2) sub.add(if2)
val if3 = PtIfElse(Position.DUMMY) val if3 = PtIfElse(Position.DUMMY)
val cmp3 = PtBinaryExpressionObsoleteUsePtRpn("<", DataType.BYTE, Position.DUMMY) val cmp3 = PtBinaryExpression("<", DataType.BYTE, Position.DUMMY)
cmp3.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp3.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp3.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY)) cmp3.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY))
if3.add(cmp3) if3.add(cmp3)
@ -315,7 +315,7 @@ class TestVmCodeGen: FunSpec({
if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if3) sub.add(if3)
val if4 = PtIfElse(Position.DUMMY) val if4 = PtIfElse(Position.DUMMY)
val cmp4 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.BYTE, Position.DUMMY) val cmp4 = PtBinaryExpression(">", DataType.BYTE, Position.DUMMY)
cmp4.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp4.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp4.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY)) cmp4.add(PtNumber(DataType.BYTE, 0.0, Position.DUMMY))
if4.add(cmp4) if4.add(cmp4)
@ -354,7 +354,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.BYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.BYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp1.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -362,7 +362,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if1.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn("!=", DataType.BYTE, Position.DUMMY) val cmp2 = PtBinaryExpression("!=", DataType.BYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp2.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)
@ -370,7 +370,7 @@ class TestVmCodeGen: FunSpec({
if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if2.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if2) sub.add(if2)
val if3 = PtIfElse(Position.DUMMY) val if3 = PtIfElse(Position.DUMMY)
val cmp3 = PtBinaryExpressionObsoleteUsePtRpn("<", DataType.BYTE, Position.DUMMY) val cmp3 = PtBinaryExpression("<", DataType.BYTE, Position.DUMMY)
cmp3.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp3.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp3.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY)) cmp3.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY))
if3.add(cmp3) if3.add(cmp3)
@ -378,7 +378,7 @@ class TestVmCodeGen: FunSpec({
if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) }) if3.add(PtNodeGroup().also { it.add(PtNop(Position.DUMMY)) })
sub.add(if3) sub.add(if3)
val if4 = PtIfElse(Position.DUMMY) val if4 = PtIfElse(Position.DUMMY)
val cmp4 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.BYTE, Position.DUMMY) val cmp4 = PtBinaryExpression(">", DataType.BYTE, Position.DUMMY)
cmp4.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY)) cmp4.add(PtIdentifier("main.start.sb1", DataType.BYTE, Position.DUMMY))
cmp4.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY)) cmp4.add(PtNumber(DataType.BYTE, 42.0, Position.DUMMY))
if4.add(cmp4) if4.add(cmp4)
@ -413,7 +413,7 @@ class TestVmCodeGen: FunSpec({
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("ub1", DataType.UBYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("ub1", DataType.UBYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
val cmp1 = PtBinaryExpressionObsoleteUsePtRpn("==", DataType.UBYTE, Position.DUMMY) val cmp1 = PtBinaryExpression("==", DataType.UBYTE, Position.DUMMY)
cmp1.add(PtIdentifier("main.start.ub1", DataType.UBYTE, Position.DUMMY)) cmp1.add(PtIdentifier("main.start.ub1", DataType.UBYTE, Position.DUMMY))
cmp1.add(PtNumber(DataType.UBYTE, 42.0, Position.DUMMY)) cmp1.add(PtNumber(DataType.UBYTE, 42.0, Position.DUMMY))
if1.add(cmp1) if1.add(cmp1)
@ -421,7 +421,7 @@ class TestVmCodeGen: FunSpec({
if1.add(PtNodeGroup()) if1.add(PtNodeGroup())
sub.add(if1) sub.add(if1)
val if2 = PtIfElse(Position.DUMMY) val if2 = PtIfElse(Position.DUMMY)
val cmp2 = PtBinaryExpressionObsoleteUsePtRpn(">", DataType.UBYTE, Position.DUMMY) val cmp2 = PtBinaryExpression(">", DataType.UBYTE, Position.DUMMY)
cmp2.add(PtIdentifier("main.start.ub1", DataType.UBYTE, Position.DUMMY)) cmp2.add(PtIdentifier("main.start.ub1", DataType.UBYTE, Position.DUMMY))
cmp2.add(PtNumber(DataType.UBYTE, 42.0, Position.DUMMY)) cmp2.add(PtNumber(DataType.UBYTE, 42.0, Position.DUMMY))
if2.add(cmp2) if2.add(cmp2)

View File

@ -456,36 +456,17 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
return arr return arr
} }
private fun transform(srcExpr: BinaryExpression): PtBinaryExpressionObsoleteUsePtRpn { private fun transform(srcExpr: BinaryExpression): PtBinaryExpression {
// NOTE: the Ast maker here will NOT create RPN-expression nodes for the code generator.
// If the code generator prefers RPN expressions, it has to transform the PtBinaryExpression itself into PtRpn.
val type = srcExpr.inferType(program).getOrElse { throw FatalAstException("unknown dt") } val type = srcExpr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
val actualType = if(type==DataType.BOOL) DataType.UBYTE else type val actualType = if(type==DataType.BOOL) DataType.UBYTE else type
val expr = PtBinaryExpressionObsoleteUsePtRpn(srcExpr.operator, actualType, srcExpr.position) val expr = PtBinaryExpression(srcExpr.operator, actualType, srcExpr.position)
expr.add(transformExpression(srcExpr.left)) expr.add(transformExpression(srcExpr.left))
expr.add(transformExpression(srcExpr.right)) expr.add(transformExpression(srcExpr.right))
return expr return expr
} }
// TODO replace the above with this, to generete RPN expression nodes:
// private fun transform(srcExpr: BinaryExpression): PtRpn {
// fun makeRpn(expr: Expression): PtRpn {
// val type = expr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
// val actualType = if(type==DataType.BOOL) DataType.UBYTE else type
// val rpn = PtRpn(actualType, expr.position)
// rpn += transformExpression(expr)
// return rpn
// }
//
// val leftDt = srcExpr.left.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
// val rightDt = srcExpr.left.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
// val type = srcExpr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
// val actualType = if(type==DataType.BOOL) DataType.UBYTE else type
// val rpn = PtRpn(actualType, srcExpr.position)
// rpn += makeRpn(srcExpr.left)
// rpn += makeRpn(srcExpr.right)
// rpn += PtRpnOperator(srcExpr.operator, actualType, leftDt, rightDt, srcExpr.position)
// return rpn
// }
private fun transform(srcCall: BuiltinFunctionCall): PtBuiltinFunctionCall { private fun transform(srcCall: BuiltinFunctionCall): PtBuiltinFunctionCall {
val type = srcCall.inferType(program).getOrElse { throw FatalAstException("unknown dt") } val type = srcCall.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
val noSideFx = BuiltinFunctions.getValue(srcCall.name).pure val noSideFx = BuiltinFunctions.getValue(srcCall.name).pure