diff --git a/codeCore/src/prog8/code/ast/AstBase.kt b/codeCore/src/prog8/code/ast/AstBase.kt index 9cc9a2bac..457d32f58 100644 --- a/codeCore/src/prog8/code/ast/AstBase.kt +++ b/codeCore/src/prog8/code/ast/AstBase.kt @@ -53,8 +53,7 @@ sealed class PtNamedNode(var name: String, position: Position): PtNode(position) class PtProgram( val name: String, val memsizer: IMemSizer, - val encoding: IStringEncoding, - var binaryExpressionsAreRPN: Boolean = false + val encoding: IStringEncoding ) : PtNode(Position.DUMMY) { // fun allModuleDirectives(): Sequence = @@ -65,53 +64,6 @@ 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() { - if(binaryExpressionsAreRPN) - return - fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn { - fun makeRpn(expr: PtExpression): PtRpn { - val rpn = PtRpn(expr.type, expr.position) - if(expr is PtBinaryExpression) - rpn.addRpnNode(transformToRPN(expr)) - else - rpn.addRpnNode(expr) - return rpn - } - - val rpn = PtRpn(originalExpr.type, originalExpr.position) - rpn.addRpnNode(makeRpn(originalExpr.left)) - rpn.addRpnNode(makeRpn(originalExpr.right)) - rpn.addRpnNode(PtRpnOperator(originalExpr.operator, originalExpr.type, originalExpr.left.type, originalExpr.right.type, originalExpr.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) } - binaryExpressionsAreRPN = true - - // extra check to see that all PtBinaryExpressions have been transformed - fun binExprCheck(node: PtNode) { - if(node is PtBinaryExpression) - throw IllegalArgumentException("still got binexpr $node ${node.position}") - node.children.forEach { binExprCheck(it) } - } - binExprCheck(this) - } } diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index c88f642d6..6adfea186 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -3,7 +3,6 @@ package prog8.code.ast import prog8.code.core.* import java.util.* import kotlin.math.abs -import kotlin.math.max import kotlin.math.round @@ -28,7 +27,6 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit 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 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 is PtMachineRegister -> other is PtMachineRegister && other.type==type && other.register==register @@ -64,7 +62,6 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit is PtArray -> true is PtArrayIndexer -> index is PtNumber || index is PtIdentifier 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 is PtFunctionCall -> false @@ -161,146 +158,6 @@ class PtBinaryExpression(val operator: String, type: DataType, position: Positio } -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. - - fun addRpnNode(node: PtNode) { - require(node is PtRpnOperator || node is PtExpression) - if(node is PtRpn) { - node.children.forEach { - children.add(it) - it.parent = this - } - } - else { - require(node !is PtBinaryExpression) - children.add(node) - node.parent = this - } - } - - fun print() { - children.forEach { - when(it) { - is PtRpnOperator -> println(it.operator) - is PtExpression -> println("expr $it ${it.position}") - else -> {} - } - } - } - - fun isSame(other: PtRpn): Boolean { - if(other.children.size==children.size) { - return other.children.zip(this.children).all { (first, second) -> - when (first) { - is PtRpnOperator -> second is PtRpnOperator && first.operator==second.operator - is PtExpression -> second is PtExpression && first isSameAs second - else -> false - } - } - } - return false - } - - fun maxDepth(): Map { - val depths = mutableMapOf( - DataType.UBYTE to 0, - DataType.UWORD to 0, - DataType.FLOAT to 0 - ) - val maxDepths = mutableMapOf( - DataType.UBYTE to 0, - DataType.UWORD to 0, - DataType.FLOAT to 0 - ) - var numPushes = 0 - var numPops = 0 - - fun push(type: DataType) { - when (type) { - in ByteDatatypes -> { - val depth = depths.getValue(DataType.UBYTE) + 1 - depths[DataType.UBYTE] = depth - maxDepths[DataType.UBYTE] = max(maxDepths.getValue(DataType.UBYTE), depth) - } - in WordDatatypes, in PassByReferenceDatatypes -> { - val depth = depths.getValue(DataType.UWORD) + 1 - depths[DataType.UWORD] = depth - maxDepths[DataType.UWORD] = max(maxDepths.getValue(DataType.UWORD), depth) - } - DataType.FLOAT -> { - val depth = depths.getValue(DataType.FLOAT) + 1 - depths[DataType.FLOAT] = depth - maxDepths[DataType.FLOAT] = max(maxDepths.getValue(DataType.FLOAT), depth) - } - else -> throw IllegalArgumentException("invalid dt") - } - numPushes++ - } - - fun pop(type: DataType) { - when (type) { - in ByteDatatypes -> depths[DataType.UBYTE]=depths.getValue(DataType.UBYTE) - 1 - in WordDatatypes, in PassByReferenceDatatypes -> depths[DataType.UWORD]=depths.getValue(DataType.UWORD) - 1 - DataType.FLOAT -> depths[DataType.FLOAT]=depths.getValue(DataType.FLOAT) - 1 - else -> throw IllegalArgumentException("invalid dt") - } - numPops++ - } - - children.withIndex().forEach { (index, node) -> - if (node is PtRpnOperator) { - pop(node.leftType) - pop(node.rightType) - push(node.type) - } - else { - push((node as PtExpression).type) - } - } - require(numPushes==numPops+1 && numPushes==children.size) { - "RPN not balanced, pushes=$numPushes pops=$numPops childs=${children.size}" - } - return maxDepths - } - - fun finalOperator() = children.last() as PtRpnOperator - fun finalLeftOperand() = children[children.size-3] - fun finalRightOperand() = children[children.size-2] - fun finalOperation() = Triple(finalLeftOperand(), finalOperator(), finalRightOperand()) - fun truncateLastOperator(): PtExpression { - // NOTE: this is a destructive operation! - children.removeLast() - children.removeLast() - if(children.last() !is PtRpnOperator) { - if(children.size==1 && children[0] is PtExpression) - return children[0] as PtExpression - else - throw IllegalArgumentException("don't know what to do with children: $children") - } - val finalOper = finalOperator() - if(finalOper.type==type) return this - val typeAdjusted = PtRpn(finalOper.type, this.position) - typeAdjusted.children.addAll(children) - typeAdjusted.parent = parent - return typeAdjusted - } -} - -class PtRpnOperator(val operator: String, val type: DataType, val leftType: DataType, val rightType: DataType, position: Position): PtNode(position) { - init { - // NOTE: For now, we require that the types of the operands are the same size as the output type of the operator node. - if(operator !in ComparisonOperators && operator != "<<" && operator != ">>") { - require(type equalsSize leftType && type equalsSize rightType) { - "operand type size(s) differ from operator result type $type: $leftType $rightType oper: $operator" - } - } - } -} - - class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, position) { val element: PtExpression get() = children[0] as PtExpression diff --git a/codeCore/src/prog8/code/ast/AstPrinter.kt b/codeCore/src/prog8/code/ast/AstPrinter.kt index 1561d9f68..f120a70b6 100644 --- a/codeCore/src/prog8/code/ast/AstPrinter.kt +++ b/codeCore/src/prog8/code/ast/AstPrinter.kt @@ -19,8 +19,6 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni is PtArray -> "array len=${node.children.size} ${type(node.type)}" is PtArrayIndexer -> " ${type(node.type)}" is PtBinaryExpression -> " ${node.operator} ${type(node.type)}" - is PtRpn -> " ${type(node.type)}" - is PtRpnOperator -> "${node.operator} ${type(node.type)}" is PtBuiltinFunctionCall -> { val str = if(node.void) "void " else "" str + node.name + "()" diff --git a/codeCore/src/prog8/code/core/CompilationOptions.kt b/codeCore/src/prog8/code/core/CompilationOptions.kt index 7e9006039..3c33ab677 100644 --- a/codeCore/src/prog8/code/core/CompilationOptions.kt +++ b/codeCore/src/prog8/code/core/CompilationOptions.kt @@ -20,7 +20,7 @@ class CompilationOptions(val output: OutputType, var asmListfile: Boolean = false, var experimentalCodegen: Boolean = false, var varsHigh: Boolean = false, - var useRPN: Boolean = false, + var useNewExprCode: Boolean = false, var evalStackBaseAddress: UInt? = null, var outputDir: Path = Path(""), var symbolDefs: Map = emptyMap() diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 19fda1f69..5d98a1130 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -21,9 +21,9 @@ class AsmGen6502: ICodeGeneratorBackend { options: CompilationOptions, errors: IErrorReporter ): IAssemblyProgram? { - if(options.useRPN) { - program.transformBinExprToRPN() - errors.warn("EXPERIMENTAL RPN EXPRESSION NODES ARE USED. CODE SIZE+SPEED WILL SUFFER.", Position.DUMMY) + if(options.useNewExprCode) { + // TODO("transform BinExprs?") + // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) } // printAst(program, true) { println(it) } @@ -551,59 +551,33 @@ class AsmGen6502Internal ( } private fun translate(stmt: PtIfElse) { - if(stmt.condition is PtRpn) { - val condition = stmt.condition as PtRpn - requireComparisonExpression(condition) // IfStatement: condition must be of form 'x ' - if (stmt.elseScope.children.isEmpty()) { - val jump = stmt.ifScope.children.singleOrNull() - if (jump is PtJump) { - translateCompareAndJumpIfTrueRPN(condition, jump) - } else { - val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalseRPN(condition, endLabel) - translate(stmt.ifScope) - out(endLabel) - } + val condition = stmt.condition as PtBinaryExpression + requireComparisonExpression(condition) // IfStatement: condition must be of form 'x ' + if (stmt.elseScope.children.isEmpty()) { + val jump = stmt.ifScope.children.singleOrNull() + if (jump is PtJump) { + translateCompareAndJumpIfTrue(condition, jump) } else { - // both true and else parts - val elseLabel = makeLabel("if_else") val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalseRPN(condition, elseLabel) + translateCompareAndJumpIfFalse(condition, endLabel) translate(stmt.ifScope) - jmp(endLabel) - out(elseLabel) - translate(stmt.elseScope) out(endLabel) } } else { - val condition = stmt.condition as PtBinaryExpression - requireComparisonExpression(condition) // IfStatement: condition must be of form 'x ' - if (stmt.elseScope.children.isEmpty()) { - val jump = stmt.ifScope.children.singleOrNull() - if (jump is PtJump) { - translateCompareAndJumpIfTrue(condition, jump) - } else { - val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, endLabel) - translate(stmt.ifScope) - out(endLabel) - } - } else { - // both true and else parts - val elseLabel = makeLabel("if_else") - val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, elseLabel) - translate(stmt.ifScope) - jmp(endLabel) - out(elseLabel) - translate(stmt.elseScope) - out(endLabel) - } + // both true and else parts + val elseLabel = makeLabel("if_else") + val endLabel = makeLabel("if_end") + translateCompareAndJumpIfFalse(condition, elseLabel) + translate(stmt.ifScope) + jmp(endLabel) + out(elseLabel) + translate(stmt.elseScope) + out(endLabel) } } private fun requireComparisonExpression(condition: PtExpression) { - if (!(condition is PtRpn && condition.finalOperator().operator in ComparisonOperators) && !(condition is PtBinaryExpression && condition.operator in ComparisonOperators)) + if (!(condition is PtBinaryExpression && condition.operator in ComparisonOperators)) throw AssemblyError("expected boolean comparison expression $condition") } @@ -766,7 +740,7 @@ $repeatLabel lda $counterVar } val isNested = parent is PtRepeatLoop - if(!isNested && !options.useRPN) { + if(!isNested && !options.useNewExprCode) { // we can re-use a counter var from the subroutine if it already has one for that datatype val existingVar = asmInfo.extraVars.firstOrNull { it.first==dt && it.second.endsWith("counter") } if(existingVar!=null) { @@ -1012,45 +986,12 @@ $repeatLabel lda $counterVar val right: PtExpression val operator: String - when (pointerOffsetExpr) { - is PtRpn -> { - if(pointerOffsetExpr.children.size>3) { - val rightmostOperator = pointerOffsetExpr.finalOperator() - if(rightmostOperator.operator=="+") { - val rightmostOperand = pointerOffsetExpr.finalRightOperand() - if ((rightmostOperand is PtNumber && rightmostOperand.type in IntegerDatatypes && rightmostOperand.number.toInt() in 0..255) - || (rightmostOperand is PtExpression && rightmostOperand.type == DataType.UBYTE) - || (rightmostOperand is PtTypeCast && rightmostOperand.value.type == DataType.UBYTE) - ) { - // split up the big expression in 2 parts so that we CAN use ZP,Y indexing after all - val truncatedExpr = pointerOffsetExpr.truncateLastOperator() - val tempvar = getTempVarName(DataType.UWORD) - assignExpressionToVariable(truncatedExpr, tempvar, DataType.UWORD) - val smallExpr = PtRpn(DataType.UWORD, truncatedExpr.position) - smallExpr.addRpnNode(PtIdentifier(tempvar, DataType.UWORD, truncatedExpr.position)) - smallExpr.addRpnNode(rightmostOperand) - smallExpr.addRpnNode(rightmostOperator) - smallExpr.parent = truncatedExpr.parent - val result = pointerViaIndexRegisterPossible(smallExpr) - require(result != null) - return result - } - } - return null // expression is too complex - } - val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation() - operator=oper.operator - if (leftNode !is PtExpression || rightNode !is PtExpression) return null - left = leftNode - right = rightNode - } - is PtBinaryExpression -> { - operator = pointerOffsetExpr.operator - left = pointerOffsetExpr.left - right = pointerOffsetExpr.right - } - else -> return null + if (pointerOffsetExpr is PtBinaryExpression) { + operator = pointerOffsetExpr.operator + left = pointerOffsetExpr.left + right = pointerOffsetExpr.right } + else return null if (operator != "+") return null val leftDt = left.type @@ -1173,53 +1114,6 @@ $repeatLabel lda $counterVar return node.definingSub()?.parameters?.singleOrNull { it.name===name } } - private fun translateCompareAndJumpIfTrueRPN(expr: PtRpn, jump: PtJump) { - val (leftRpn, oper, right) = expr.finalOperation() - if(oper.operator !in ComparisonOperators) - throw AssemblyError("must be comparison expression") - val left: PtExpression = if(expr.children.size>3 || leftRpn !is PtExpression) - expr.truncateLastOperator() - else - leftRpn - - // invert the comparison, so we can reuse the JumpIfFalse code generation routines - val invertedComparisonOperator = invertedComparisonOperator(oper.operator) - ?: throw AssemblyError("can't invert comparison $expr") - - val label = when { - jump.generatedLabel!=null -> jump.generatedLabel!! - jump.identifier!=null -> asmSymbolName(jump.identifier!!) - jump.address!=null -> jump.address!!.toHex() - else -> throw AssemblyError("weird jump") - } - val rightConstVal = right as? PtNumber - if (rightConstVal!=null && rightConstVal.number == 0.0) { - testZeroAndJump(left, invertedComparisonOperator, label) - } - else { - require(right is PtExpression) - val leftConstVal = left as? PtNumber - testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal) - } - } - - private fun translateCompareAndJumpIfFalseRPN(expr: PtRpn, jumpIfFalseLabel: String) { - val (leftRpn, oper, right) = expr.finalOperation() - val left: PtExpression = if(expr.children.size>3 || leftRpn !is PtExpression) - expr.truncateLastOperator() - else - leftRpn - - require(right is PtExpression) - val leftConstVal = left as? PtNumber - val rightConstVal = right as? PtNumber - - if (rightConstVal!=null && rightConstVal.number == 0.0) - testZeroAndJump(left, oper.operator, jumpIfFalseLabel) - else - testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal) - } - private fun translateCompareAndJumpIfTrue(expr: PtBinaryExpression, jump: PtJump) { if(expr.operator !in ComparisonOperators) throw AssemblyError("must be comparison expression") @@ -2967,15 +2861,6 @@ $repeatLabel lda $counterVar assignViaExprEval() } } - is PtRpn -> { - val addrExpr = expr.address as PtRpn - if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { - if(pushResultOnEstack) - out(" sta P8ESTACK_LO,x | dex") - } else { - assignViaExprEval() - } - } else -> assignViaExprEval() } } @@ -3205,7 +3090,6 @@ internal class SubroutineExtraAsmInfo { var usedRegsaveY = false var usedFloatEvalResultVar1 = false var usedFloatEvalResultVar2 = false - var rpnDepth = 0 // 'depth' tracking of the RPN expression evaluator val extraVars = mutableListOf>() } \ No newline at end of file diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 18b9e7707..79b6f3d2d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -661,7 +661,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, return } } - is PtRpn, is PtBinaryExpression -> { + is PtBinaryExpression -> { val result = asmgen.pointerViaIndexRegisterPossible(addrExpr) val pointer = result?.first as? PtIdentifier if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) { @@ -723,7 +723,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } } else fallback() } - is PtRpn, is PtBinaryExpression -> { + is PtBinaryExpression -> { val result = asmgen.pointerViaIndexRegisterPossible(addrExpr) val pointer = result?.first as? PtIdentifier if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt index 9993aca40..0e80ba5cc 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt @@ -25,7 +25,6 @@ internal class ExpressionsAsmGen(private val program: PtProgram, when(expression) { is PtPrefix -> translateExpression(expression) is PtBinaryExpression -> translateExpression(expression) - is PtRpn -> translateRpnExpression(expression) is PtArrayIndexer -> translateExpression(expression) is PtTypeCast -> translateExpression(expression) is PtAddressOf -> translateExpression(expression) @@ -245,70 +244,8 @@ internal class ExpressionsAsmGen(private val program: PtProgram, } } - private fun translateRpnExpression(expr: PtRpn) { - // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! - val (left, oper, right) = expr.finalOperation() - if(left is PtExpression && right is PtExpression && translateSomewhatOptimized(left, oper.operator, right)) - return - - val leftDt = oper.leftType - val rightDt = oper.rightType - - // comparison with zero - if(oper.operator in ComparisonOperators && leftDt in NumericDatatypes && rightDt in NumericDatatypes) { - val rightVal = (expr.finalRightOperand() as PtExpression).asConstInteger() - if (rightVal == 0) { - when (left) { - is PtExpression -> { - translateComparisonWithZero(left, leftDt, oper.operator) - } - is PtRpnOperator -> { - val truncated = expr.truncateLastOperator() - translateComparisonWithZero(truncated, leftDt, oper.operator) - } - else -> throw AssemblyError("weird rpn node") - } - return - } - } - - // string compare - if(left is PtExpression && leftDt==DataType.STR && rightDt==DataType.STR && oper.operator in ComparisonOperators) - return translateCompareStrings(left, oper.operator, expr.finalRightOperand() as PtExpression) - - // any other expression - if((leftDt in ByteDatatypes && rightDt !in ByteDatatypes) - || (leftDt in WordDatatypes && rightDt !in WordDatatypes)) - throw AssemblyError("operator ${oper.operator} left/right dt not identical: $leftDt $rightDt right=${expr.finalRightOperand()}") - - val asmExtra = asmgen.subroutineExtra(expr.definingISub()!!) - val startDepth = asmExtra.rpnDepth - expr.children.forEach { - if(it is PtRpnOperator) { - when(it.leftType) { - in ByteDatatypes -> translateBinaryOperatorBytes(it.operator, it.leftType) - in WordDatatypes -> translateBinaryOperatorWords(it.operator, it.leftType) - DataType.FLOAT -> translateBinaryOperatorFloats(it.operator) - DataType.STR -> { - if(it.operator !in ComparisonOperators) - throw AssemblyError("expected only comparison operators on string, not ${oper.operator}") - asmgen.out(" jsr prog8_lib.strcmp_stack") - compareStringsProcessResultInA(it.operator) - } - else -> throw AssemblyError("non-numerical datatype ${it.leftType}") - } - asmExtra.rpnDepth-- - } else { - translateExpressionInternal(it as PtExpression) - asmExtra.rpnDepth++ - } - } - require(asmExtra.rpnDepth-startDepth==1) { "unbalanced RPN: ${expr.position}" } - } - private fun translateExpression(expr: PtBinaryExpression) { // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! - require(!program.binaryExpressionsAreRPN) if(translateSomewhatOptimized(expr.left, expr.operator, expr.right)) return diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index aad922ddf..64c6b0008 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -146,14 +146,6 @@ internal class AssignmentAsmGen(private val program: PtProgram, is PtIdentifier -> { assignMemoryByte(assign.target, null, value.address as PtIdentifier) } - is PtRpn -> { - val addrExpr = value.address as PtRpn - if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { - assignRegisterByte(assign.target, CpuRegister.A) - } else { - assignViaExprEval(value.address) - } - } is PtBinaryExpression -> { val addrExpr = value.address as PtBinaryExpression if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { @@ -309,7 +301,6 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignRegisterByte(assign.target, CpuRegister.A) } is PtBinaryExpression -> { - require(!program.binaryExpressionsAreRPN) if(!attemptAssignOptimizedBinexpr(value, assign)) { // 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, @@ -317,15 +308,6 @@ internal class AssignmentAsmGen(private val program: PtProgram, fallbackToStackEval(assign) } } - is PtRpn -> { - if(!attemptAssignOptimizedExprRPN(assign, scope!!)) { - // All remaining binary expressions just evaluate via the stack for now. - // TODO: For RPN expressions this should never occur anymore and the eval stack should be removed when we achieve this - // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, - // because the code here is the implementation of exactly that...) - fallbackToStackEval(assign) - } - } else -> throw AssemblyError("weird assignment value type $value") } } @@ -363,234 +345,6 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } - private fun attemptAssignOptimizedExprRPN(assign: AsmAssignment, scope: IPtSubroutine): Boolean { - val value = assign.source.expression as PtRpn - val (left, oper, right) = value.finalOperation() - if(oper.type != value.type) - throw AssemblyError("rpn node type error, expected ${value.type} got ${oper.type}") - - if(value.children.size==3 && left is PtExpression && right is PtExpression) { - - // TODO re-enable after compiler errors are fixed: -// if(right.asConstInteger() == 0) { -// if(oper.operator == "==" || oper.operator=="!=") { -// when(assign.target.datatype) { -// in ByteDatatypes -> if(attemptAssignToByteCompareZeroRPN(value, assign)) return true -// else -> { -// // do nothing, this is handled by a type cast. -// } -// } -// } -// } - - if(assign.target.datatype == oper.type && oper.leftType == oper.type) { - println("TODO simple augmented assign operator into target: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") - println(" left=$left right=$right") - //augmentableAsmGen.translate() - } else { - println("TODO augmented assign operator into target but needs tempvar: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") - println(" left=$left right=$right") - } -// if(oper.operator in ComparisonOperators) { -// println("TODO simple comparison: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") -// } -// else if(oper.operator in setOf("&", "|", "^", "and", "or", "xor")) { -// println("TODO simple logical: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") -// } -// else if(oper.operator=="+" || oper.operator=="-") { -// println("TODO simple plus or minus: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") -// } -// else if(oper.operator=="<<" || oper.operator==">>") { -// println("TODO simple bitshift: ${assign.position} ${oper.leftType} ${oper.operator} ${oper.rightType} -> ${oper.type}") -// } - } - - // TODO RPN optimizations for simple cases -// if(oper.operator in ComparisonOperators) { -// assignRPNComparison(assign, value) -// return true -// } -// -// if(right is PtExpression) { -// if (simpleEqualityExprRPN(value, oper, right, assign.target)) -// return true -// if (simpleLogicalExprRPN(value, oper, right, assign.target)) -// return true -// if (simplePlusOrMinusExprRPN(value, oper, right, assign.target)) -// return true -// if (simpleBitshiftExprRPN(value, oper, right, assign.target)) -// return true -// } - - val asmExtra = asmgen.subroutineExtra(scope) - val evalVars = mutableMapOf ( - DataType.UBYTE to Stack(), - DataType.UWORD to Stack(), - DataType.FLOAT to Stack() - ) - - fun getVarDt(dt: DataType) = - when(dt) { - in ByteDatatypes -> DataType.UBYTE - in WordDatatypes, in PassByReferenceDatatypes -> DataType.UWORD - else -> dt - } - - fun evalVarName(dt: DataType, depth: Int): String { - val name: String - val varDt: DataType - when(dt) { - in ByteDatatypes -> { - name = "p8_rpn_eval_byte_$depth" - varDt = DataType.UBYTE - } - in WordDatatypes, in PassByReferenceDatatypes -> { - name = "p8_rpn_eval_word_$depth" - varDt = DataType.UWORD - } - DataType.FLOAT -> { - name = "p8_rpn_eval_float_$depth" - varDt = DataType.FLOAT - } - else -> throw AssemblyError("weird dt") - } - evalVars.getValue(varDt).push(name) - if(!asmExtra.extraVars.any { it.second==name }) { - val stScope = symbolTable.lookup((scope as PtNamedNode).scopedName)!! - val dummyNode = PtVariable(name, varDt, ZeropageWish.DONTCARE, null, null, Position.DUMMY) - dummyNode.parent = scope - stScope.add(StStaticVariable(name, varDt, null, null, null, null, ZeropageWish.DONTCARE, dummyNode)) - asmExtra.extraVars.add(Triple(varDt, name, null)) - } - return name - } - - val startDepth = asmExtra.rpnDepth - value.children.forEach { - when (it) { - is PtRpnOperator -> { - val rightvar = evalVars.getValue(getVarDt(it.rightType)).pop() - val leftvar = evalVars.getValue(getVarDt(it.leftType)).pop() - asmExtra.rpnDepth -= 2 - val resultVarname = evalVarName(it.type, asmExtra.rpnDepth) - asmExtra.rpnDepth++ - symbolTable.resetCachedFlat() - - val scopeName = (scope as PtNamedNode).scopedName - val leftVarPt = PtIdentifier("$scopeName.$leftvar", it.leftType, it.position) - leftVarPt.parent = scope - if(it.rightType largerThan it.type) { - if(it.operator !in ComparisonOperators) - throw AssemblyError("only expected a boolean comparison, got ${it.operator}") - if(it.rightType !in WordDatatypes || it.type !in ByteDatatypes) { - when (it.rightType) { - DataType.STR -> { - val rightString = PtIdentifier("$scopeName.$rightvar", DataType.STR, it.position) - rightString.parent = scope - asmgen.assignExpressionToVariable(leftVarPt, "prog8_lib.strcmp_expression._arg_s1", DataType.UWORD) - asmgen.assignExpressionToVariable(rightString, "prog8_lib.strcmp_expression._arg_s2", DataType.UWORD) - asmgen.out(" jsr prog8_lib.strcmp_expression") // result of compare is in A - when(it.operator) { - "==" -> asmgen.out(" and #1 | eor #1") - "!=" -> asmgen.out(" and #1") - "<=" -> asmgen.out(""" - bpl + - lda #1 - bne ++ -+ lda #0 -+""") - ">=" -> asmgen.out(""" - bmi + - lda #1 - bne ++ -+ lda #0 -+""") - "<" -> asmgen.out(""" - bmi + - lda #0 - beq ++ -+ lda #1 -+""") - ">" -> asmgen.out(""" - bpl + - lda #0 - beq ++ -+ lda #1 -+""") - } - asmgen.out(" sta $resultVarname") - } - in NumericDatatypes -> { - val jumpIfFalseLabel = asmgen.makeLabel("cmp") - val rightVarPt = PtIdentifier("$scopeName.$rightvar", it.rightType, it.position) - rightVarPt.parent = scope - asmgen.testNonzeroComparisonAndJump(leftVarPt, it.operator, rightVarPt, jumpIfFalseLabel, null, null) - asmgen.out(""" - lda #1 - bne + -$jumpIfFalseLabel lda #0 - + sta $resultVarname""") - } - else -> throw AssemblyError("weird type for operator: ${it.rightType}") - } - } else { - // use in-place assignment with optional cast to the target variable - val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, it.rightType, variableAsmName = rightvar) - val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, it.leftType, scope, assign.position, variableAsmName = leftvar) - val operator = if(it.operator in ComparisonOperators) it.operator else it.operator+'=' - val augAssign = AsmAugmentedAssignment(src, operator, target, program.memsizer, assign.position) - augmentableAsmGen.translate(augAssign, scope) - if(resultVarname!=leftvar) - assignTypeCastedIdentifier(resultVarname, it.type, leftvar, it.leftType) - } - } else { - // use in-place assignment with optional cast to the target variable - val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, it.rightType, variableAsmName = rightvar) - val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, it.leftType, scope, assign.position, variableAsmName = leftvar) - val operator = if(it.operator in ComparisonOperators) it.operator else it.operator+'=' - val augAssign = AsmAugmentedAssignment(src, operator, target, program.memsizer, assign.position) - augmentableAsmGen.translate(augAssign, scope) - if(resultVarname!=leftvar) - assignTypeCastedIdentifier(resultVarname, it.type, leftvar, it.leftType) - } - } - is PtExpression -> { - val varname = evalVarName(it.type, asmExtra.rpnDepth) - assignExpressionToVariable(it, varname, it.type) - asmExtra.rpnDepth++ - } - else -> throw AssemblyError("weird rpn node") - } - } - require(asmExtra.rpnDepth-startDepth == 1) { - "unbalanced RPN ${value.position}" - } - - val resultVariable = evalVars.getValue(getVarDt(value.type)).pop() - asmExtra.rpnDepth-- - if(!(assign.target.datatype equalsSize value.type)) { - // we only allow for transparent byte -> word / ubyte -> uword assignments - // any other type difference is an error - if(assign.target.datatype in WordDatatypes && value.type in ByteDatatypes) { - assignVariableToRegister(resultVariable, RegisterOrPair.A, value.type==DataType.BYTE, scope, assign.position) - asmgen.signExtendAYlsb(value.type) - assignRegisterpairWord(assign.target, RegisterOrPair.AY) - } else { - throw AssemblyError("data type mismatch, missing typecast ${value.type} -> ${assign.target.datatype}") - } - } else { - when (value.type) { - in ByteDatatypes -> assignVariableByte(assign.target, resultVariable) - in WordDatatypes -> assignVariableWord(assign.target, resultVariable) - DataType.FLOAT -> assignVariableFloat(assign.target, resultVariable) - else -> throw AssemblyError("weird dt") - } - } - require(evalVars.all { it.value.isEmpty() }) { "invalid rpn evaluation" } - - return true - } - private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { if(expr.operator in ComparisonOperators) { if(expr.right.asConstInteger() == 0) { @@ -973,82 +727,6 @@ $jumpIfFalseLabel lda #0 assignRegisterpairWord(target, RegisterOrPair.AY) } - private fun attemptAssignToByteCompareZeroRPN(expr: PtRpn, assign: AsmAssignment): Boolean { - val (leftRpn, oper, right) = expr.finalOperation() - val left = if(expr.children.size!=3 || leftRpn !is PtExpression) - expr.truncateLastOperator() - else - leftRpn - when (oper.operator) { - "==" -> { - when(val dt = left.type) { - in ByteDatatypes -> { - assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE) - asmgen.out(""" - beq + - lda #0 - beq ++ -+ lda #1 -+""") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - in WordDatatypes -> { - assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) - asmgen.out(""" - sty P8ZP_SCRATCH_B1 - ora P8ZP_SCRATCH_B1 - beq + - lda #0 - beq ++ -+ lda #1 -+""") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - DataType.FLOAT -> { - assignExpressionToRegister(left, RegisterOrPair.FAC1, true) - asmgen.out(" jsr floats.SIGN | and #1 | eor #1") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - else->{ - return false - } - } - } - "!=" -> { - when(val dt = left.type) { - in ByteDatatypes -> { - assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE) - asmgen.out(" beq + | lda #1") - asmgen.out("+") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - in WordDatatypes -> { - assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) - asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1") - asmgen.out(" beq + | lda #1") - asmgen.out("+") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - DataType.FLOAT -> { - assignExpressionToRegister(left, RegisterOrPair.FAC1, true) - asmgen.out(" jsr floats.SIGN") - assignRegisterByte(assign.target, CpuRegister.A) - return true - } - else->{ - return false - } - } - } - else -> return false - } - } - private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { when (expr.operator) { "==" -> { @@ -1228,15 +906,6 @@ $jumpIfFalseLabel lda #0 is PtIdentifier -> { assignMemoryByteIntoWord(target, null, value.address as PtIdentifier) } - is PtRpn -> { - val addrExpr = value.address as PtRpn - if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { - asmgen.out(" ldy #0") - assignRegisterpairWord(target, RegisterOrPair.AY) - } else { - assignViaExprEval(value.address) - } - } is PtBinaryExpression -> { val addrExpr = value.address as PtBinaryExpression if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { @@ -3159,10 +2828,6 @@ $jumpIfFalseLabel lda #0 addressExpr is PtIdentifier -> { asmgen.storeAIntoPointerVar(addressExpr) } - addressExpr is PtRpn -> { - if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true)) - storeViaExprEval() - } addressExpr is PtBinaryExpression -> { if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true)) storeViaExprEval() diff --git a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt index 18d5fb90a..a2782af40 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt @@ -14,9 +14,9 @@ class ExperiCodeGen: ICodeGeneratorBackend { errors: IErrorReporter ): IAssemblyProgram? { - if(options.useRPN) { - program.transformBinExprToRPN() - errors.warn("EXPERIMENTAL RPN EXPRESSION NODES ARE USED. CODE SIZE+SPEED WILL SUFFER.", Position.DUMMY) + if(options.useNewExprCode) { + // TODO("transform BinExprs?") + // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) } // you could write a code generator directly on the PtProgram AST, diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index b406f3b2b..f76fe32dd 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -92,13 +92,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express value.add(origAssign.value) } else { require(origAssign.operator.endsWith('=')) - if(codeGen.program.binaryExpressionsAreRPN) { - value = PtRpn(origAssign.value.type, origAssign.value.position) - val left = origAssign.target.children.single() as PtExpression - val right = origAssign.value - value.add(left) - value.add(right) - value.add(PtRpnOperator(origAssign.operator.dropLast(1), origAssign.target.type, left.type, right.type, origAssign.position)) + if(codeGen.options.useNewExprCode) { + TODO("use something else than a BinExpr?") } else { value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position) val left: PtExpression = origAssign.target.children.single() as PtExpression @@ -272,13 +267,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express expressionEval.translateExpression(array.index) } else { val mult : PtExpression - if(codeGen.program.binaryExpressionsAreRPN) { - mult = PtRpn(DataType.UBYTE, array.position) - val left = array.index - val right = PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position) - mult.add(left) - mult.add(right) - mult.add(PtRpnOperator("*", DataType.UBYTE, left.type, right.type, array.position)) + if(codeGen.options.useNewExprCode) { + TODO("use something else than a BinExpr?") } else { mult = PtBinaryExpression("*", DataType.UBYTE, array.position) mult.children += array.index diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index ffd29c0ee..2363acc9a 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -93,7 +93,6 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { is PtPrefix -> translate(expr) is PtArrayIndexer -> translate(expr) is PtBinaryExpression -> translate(expr) - is PtRpn -> translate(expr) is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr) is PtFunctionCall -> translate(expr) is PtContainmentCheck -> translate(expr) @@ -316,10 +315,6 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg2, actualResultFpReg2) } - private fun translate(rpn: PtRpn): ExpressionCodeResult { - TODO("RPN expression (intermediate codegen) $rpn") - } - private fun translate(binExpr: PtBinaryExpression): ExpressionCodeResult { val vmDt = codeGen.irType(binExpr.left.type) val signed = binExpr.left.type in SignedDatatypes diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 918eaeb0e..80b89036b 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -269,8 +269,6 @@ class IRCodeGen( is PtProgram, is PtArrayIndexer, is PtBinaryExpression, - is PtRpn, - is PtRpnOperator, is PtIdentifier, is PtWhenChoice, is PtPrefix, @@ -912,39 +910,14 @@ class IRCodeGen( else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed) } } - is PtRpn -> { - val (left, oper, right) = condition.finalOperation() - if(oper.operator !in ComparisonOperators) - throw AssemblyError("if condition should only be a binary comparison expression") - - val signed = oper.leftType in SignedDatatypes - val irDtLeft = irType(oper.leftType) - return when { - goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGotoRPN(ifElse, goto, irDtLeft, signed) - constValue(right as PtExpression) == 0.0 -> translateIfElseZeroComparisonRPN(ifElse, irDtLeft, signed) - else -> translateIfElseNonZeroComparisonRPN(ifElse, irDtLeft, signed) - } - } else -> { throw AssemblyError("weird condition node: $condition") } } } - private fun translateIfFollowedByJustGotoRPN(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList { - TODO("RPN translateIfFollowedByJustGotoRPN") - } - - private fun translateIfElseZeroComparisonRPN(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { - TODO("RPN translateIfElseZeroComparisonRPN") - } - - private fun translateIfElseNonZeroComparisonRPN(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { - TODO("RPN translateIfElseNonZeroComparisonRPN") - } private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList { - require(!program.binaryExpressionsAreRPN) val condition = ifElse.condition as PtBinaryExpression val result = mutableListOf() if (irDtLeft == IRDataType.FLOAT) { @@ -1010,7 +983,6 @@ class IRCodeGen( irDtLeft: IRDataType, goto: PtJump ): MutableList { - require(!program.binaryExpressionsAreRPN) val condition = ifElse.condition as PtBinaryExpression val leftTr = expressionEval.translateExpression(condition.left) addToResult(result, leftTr, leftTr.resultReg, -1) @@ -1039,7 +1011,6 @@ class IRCodeGen( irDtLeft: IRDataType, goto: PtJump ): MutableList { - require(!program.binaryExpressionsAreRPN) val condition = ifElse.condition as PtBinaryExpression val leftTr = expressionEval.translateExpression(condition.left) addToResult(result, leftTr, leftTr.resultReg, -1) @@ -1093,7 +1064,6 @@ class IRCodeGen( } private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { - require(!program.binaryExpressionsAreRPN) val result = mutableListOf() val elseBranch: Opcode val compResultReg: Int @@ -1155,7 +1125,6 @@ class IRCodeGen( } private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { - require(!program.binaryExpressionsAreRPN) val result = mutableListOf() val elseBranchOpcode: Opcode val elseBranchFirstReg: Int diff --git a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt index 9d96de92a..5b1995599 100644 --- a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt @@ -15,9 +15,9 @@ class VmCodeGen: ICodeGeneratorBackend { errors: IErrorReporter ): IAssemblyProgram? { - if(options.useRPN) { - program.transformBinExprToRPN() - errors.warn("EXPERIMENTAL RPN EXPRESSION NODES ARE USED. CODE SIZE+SPEED WILL SUFFER.", Position.DUMMY) + if(options.useNewExprCode) { + // TODO("transform BinExprs?") + // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) } diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index ad14fa480..1c85e32d4 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -52,7 +52,7 @@ private fun compileMain(args: Array): Boolean { val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM") val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)") val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program") - val useRPN by cli.option(ArgType.Boolean, fullName = "rpn", description = "use RPN for expression code-generation (experimental)") + val useNewExprCode by cli.option(ArgType.Boolean, fullName = "newexpr", description = "use new expression code-gen (experimental)") val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) try { @@ -127,7 +127,7 @@ private fun compileMain(args: Array): Boolean { asmListfile == true, experimentalCodegen == true, varsHigh == true, - useRPN == true, + useNewExprCode == true, compilationTarget, evalStackAddr, processedSymbols, @@ -192,7 +192,7 @@ private fun compileMain(args: Array): Boolean { asmListfile == true, experimentalCodegen == true, varsHigh == true, - useRPN == true, + useNewExprCode == true, compilationTarget, evalStackAddr, processedSymbols, diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index b25cb70cb..d7d45b277 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -6,11 +6,9 @@ import prog8.ast.Program import prog8.ast.base.AstException import prog8.ast.expressions.Expression import prog8.ast.expressions.NumericLiteral -import prog8.ast.printProgram import prog8.ast.statements.Directive import prog8.code.SymbolTableMaker import prog8.code.ast.PtProgram -import prog8.code.ast.printAst import prog8.code.core.* import prog8.code.target.* import prog8.codegen.vm.VmCodeGen @@ -38,7 +36,7 @@ class CompilerArguments(val filepath: Path, val asmListfile: Boolean, val experimentalCodegen: Boolean, val varsHigh: Boolean, - val useRPN: Boolean, + val useNewExprCode: Boolean, val compilationTarget: String, val evalStackBaseAddress: UInt?, val symbolDefs: Map, @@ -79,7 +77,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? { asmListfile = args.asmListfile experimentalCodegen = args.experimentalCodegen varsHigh = args.varsHigh - useRPN = args.useRPN + useNewExprCode = args.useNewExprCode evalStackBaseAddress = args.evalStackBaseAddress outputDir = args.outputDir.normalize() symbolDefs = args.symbolDefs diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index 750fb58cf..152ef229e 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -452,8 +452,6 @@ class IntermediateAstMaker(private val program: Program, private val options: Co } 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 actualType = if(type==DataType.BOOL) DataType.UBYTE else type val expr = PtBinaryExpression(srcExpr.operator, actualType, srcExpr.position) diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 4d7b579f5..5fc22c4c3 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -33,7 +33,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat asmListfile = false, experimentalCodegen = false, varsHigh = false, - useRPN = false, + useNewExprCode = false, compilationTarget = target.name, evalStackBaseAddress = null, symbolDefs = emptyMap(), diff --git a/compiler/test/TestCompilerOptionLibdirs.kt b/compiler/test/TestCompilerOptionLibdirs.kt index dcbf80f47..bcdafab38 100644 --- a/compiler/test/TestCompilerOptionLibdirs.kt +++ b/compiler/test/TestCompilerOptionLibdirs.kt @@ -50,7 +50,7 @@ class TestCompilerOptionSourcedirs: FunSpec({ asmListfile = false, experimentalCodegen = false, varsHigh = false, - useRPN = false, + useNewExprCode = false, compilationTarget = Cx16Target.NAME, evalStackBaseAddress = null, symbolDefs = emptyMap(), diff --git a/compiler/test/codegeneration/TestRPNCodeGen.kt b/compiler/test/codegeneration/TestRPNCodeGen.kt deleted file mode 100644 index 64b29321c..000000000 --- a/compiler/test/codegeneration/TestRPNCodeGen.kt +++ /dev/null @@ -1,45 +0,0 @@ -package prog8tests.codegeneration - -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import prog8.code.ast.PtAssignment -import prog8.code.ast.PtBuiltinFunctionCall -import prog8.code.ast.PtRpn -import prog8.code.core.DataType -import prog8.code.target.C64Target -import prog8tests.helpers.compileText - -class TestRPNCodeGen: FunSpec({ - test("rpn 6502") { - val text=""" -main { - sub start() { - uword pointer = 4000 - uword a = 11 - uword b = 22 - uword c = 33 - cx16.r0 = peekw(pointer+a+b*c+42) - pokew(pointer+a+b*c+42, 4242) - } -}""" - val result = compileText(C64Target(), false, text, writeAssembly = true, useRPN = true)!! - val ast = result.codegenAst!! - val statements = ast.entrypoint()!!.children - statements.size shouldBe 11 - val peekw = (statements[8] as PtAssignment).value as PtBuiltinFunctionCall - val pokew = (statements[9] as PtBuiltinFunctionCall) - val rpn1 = peekw.args.first() as PtRpn - val rpn2 = pokew.args.first() as PtRpn - rpn1.children.size shouldBe 7 - val depth1 = rpn1.maxDepth() - depth1.getValue(DataType.UBYTE) shouldBe 0 - depth1.getValue(DataType.UWORD) shouldBe 3 - depth1.getValue(DataType.FLOAT) shouldBe 0 - rpn2.children.size shouldBe 7 - val depth2 = rpn2.maxDepth() - depth2.getValue(DataType.UBYTE) shouldBe 0 - depth2.getValue(DataType.UWORD) shouldBe 3 - depth2.getValue(DataType.FLOAT) shouldBe 0 - } - -}) \ No newline at end of file diff --git a/compiler/test/codegeneration/TestVariousCodeGen.kt b/compiler/test/codegeneration/TestVariousCodeGen.kt index 2ecdc9ad2..88546de82 100644 --- a/compiler/test/codegeneration/TestVariousCodeGen.kt +++ b/compiler/test/codegeneration/TestVariousCodeGen.kt @@ -160,9 +160,9 @@ main { qq = 16000 + c*${'$'}0008 } }""" - compileText(C64Target(), true, text, writeAssembly = true, useRPN = false) shouldNotBe null - compileText(C64Target(), true, text, writeAssembly = true, useRPN = true) shouldNotBe null - compileText(VMTarget(), true, text, writeAssembly = true, useRPN = false) shouldNotBe null - // TODO RPN once IR RPN codegen is done: compileText(VMTarget(), true, text, writeAssembly = true, useRPN = true) shouldNotBe null + compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null + compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null + compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null + compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null } }) \ No newline at end of file diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index a2362e8bb..ceefdde25 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -18,7 +18,7 @@ internal fun compileFile( errors: IErrorReporter? = null, writeAssembly: Boolean = true, optFloatExpr: Boolean = true, - useRPN: Boolean = false + useNewExprCode: Boolean = false ) : CompilationResult? { val filepath = fileDir.resolve(fileName) assumeReadableFile(filepath) @@ -32,7 +32,7 @@ internal fun compileFile( asmListfile = false, experimentalCodegen = false, varsHigh = false, - useRPN = useRPN, + useNewExprCode = useNewExprCode, platform.name, evalStackBaseAddress = null, symbolDefs = emptyMap(), @@ -54,11 +54,11 @@ internal fun compileText( errors: IErrorReporter? = null, writeAssembly: Boolean = true, optFloatExpr: Boolean = true, - useRPN: Boolean = false + useNewExprCode: Boolean = false ) : CompilationResult? { val filePath = outputDir.resolve("on_the_fly_test_" + sourceText.hashCode().toUInt().toString(16) + ".p8") // we don't assumeNotExists(filePath) - should be ok to just overwrite it filePath.toFile().writeText(sourceText) return compileFile(platform, optimize, filePath.parent, filePath.name, - errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr, useRPN=useRPN) + errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr, useNewExprCode=useNewExprCode) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index bee8b8c60..954526c3a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,26 +1,14 @@ TODO ==== + replace RPN by something that actually works and is efficient... -RPN: assembler fails selftest (something with output file name extension being wrong!) -RPN: swirl is MUCH slower -RPN: wizzine is slightly slower -RPN: bsieve is much slower - -then: -RPN: swirl is bigger -RPN: petaxian is 900 bytes larger, chess is a lot bigger -RPN: cube3d is much larger, but a bit faster -RPN: cube3d-float is massive and slow -RPN: mandelbrot is bigger, but seems faster -RPN: Implement RPN codegen for IR. - For next minor release ^^^^^^^^^^^^^^^^^^^^^^ -- ubyte fits = cx