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
+34
View File
@@ -64,6 +64,40 @@ class PtProgram(
fun entrypoint(): 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) }
}
}
+25 -10
View File
@@ -27,7 +27,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
return when(this) {
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 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 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
@@ -63,7 +63,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
is PtAddressOf -> true
is PtArray -> true
is PtArrayIndexer -> index is PtNumber || index is PtIdentifier
is PtBinaryExpressionObsoleteUsePtRpn -> false
is PtBinaryExpression -> false
is PtRpn -> false
is PtBuiltinFunctionCall -> name in arrayOf("msb", "lsb", "peek", "peekw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd")
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 &, |, ^.
val left: 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) {
// 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)
if(node is PtRpn)
children.addAll(node.children)
else
if(node is PtRpn) {
node.children.forEach {
children += it
it.parent = this
}
}
else {
children += node
node.parent = this
}
}
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) {
init {
require(type==operand1Type && type==operand2Type) // TODO if this is always true, can remove operand1 and 2 types again.
}
// init {
// 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"
// }
// }
// }
}
+1 -1
View File
@@ -18,7 +18,7 @@ fun printAst(root: PtNode, output: (text: String) -> Unit) {
is PtAddressOf -> "&"
is PtArray -> "array len=${node.children.size} ${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 PtRpnOperator -> node.operator
is PtBuiltinFunctionCall -> {
+2 -2
View File
@@ -100,8 +100,8 @@ class PtForLoop(position: Position) : PtNode(position) {
class PtIfElse(position: Position) : PtNode(position) {
val condition: PtBinaryExpressionObsoleteUsePtRpn
get() = children[0] as PtBinaryExpressionObsoleteUsePtRpn
val condition: PtNode
get() = children[0] as PtNode
val ifScope: PtNodeGroup
get() = children[1] as PtNodeGroup
val elseScope: PtNodeGroup