fix string compare and ifelse

This commit is contained in:
Irmen de Jong 2023-03-28 21:32:59 +02:00
parent 07fde7f6cc
commit f4bf00ad31
4 changed files with 48 additions and 25 deletions

View File

@ -583,15 +583,15 @@ class AsmGen6502Internal (
else -> throw AssemblyError("weird jump")
}
when(stmt.condition.type) {
in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, label)
in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, label)
in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, label)
in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, label)
else -> throw AssemblyError("weird condition dt")
}
} else {
val endLabel = makeLabel("if_end")
when(stmt.condition.type) {
in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
else -> throw AssemblyError("weird condition dt")
}
translate(stmt.ifScope)

View File

@ -70,17 +70,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
"rrestorex" -> funcRrestoreX()
"cmp" -> funcCmp(fcall)
"callfar" -> funcCallFar(fcall)
"prog8_lib_stringcompare" -> funcStringCompare(fcall)
"prog8_lib_stringcompare" -> funcStringCompare(fcall, resultToStack)
else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}")
}
return BuiltinFunctions.getValue(fcall.name).returnType
}
private fun funcStringCompare(fcall: PtBuiltinFunctionCall) {
private fun funcStringCompare(fcall: PtBuiltinFunctionCall, resultToStack: Boolean) {
assignAsmGen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W2", DataType.UWORD)
assignAsmGen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY, false)
asmgen.out(" jsr prog8_lib.strcmp_mem")
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
}
private fun funcRsave() {

View File

@ -4,6 +4,7 @@ import com.github.michaelbull.result.onFailure
import prog8.ast.IBuiltinFunctions
import prog8.ast.Program
import prog8.ast.base.AstException
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.Expression
import prog8.ast.expressions.NumericLiteral
import prog8.ast.statements.Directive
@ -428,9 +429,28 @@ private fun createAssemblyAndAssemble(program: PtProgram,
private fun transformNewExpressions(program: PtProgram) {
val newVariables = mutableMapOf<PtSub, MutableList<PtVariable>>()
var countByteVars = 0
var countWordVars = 0
var countFloatVars = 0
// TODO: find a reliable way to reuse the temp vars across expressions
fun getExprVar(what: String, type: DataType, count: Int, pos: Position, scope: PtSub): PtIdentifier {
val name = "p8p_exprvar_${what}_${count}_${type.toString().lowercase()}"
fun getExprVar(type: DataType, pos: Position, scope: PtSub): PtIdentifier {
val count = when(type) {
in ByteDatatypes -> {
countByteVars++
countByteVars
}
in WordDatatypes -> {
countWordVars++
countWordVars
}
DataType.FLOAT -> {
countFloatVars++
countFloatVars
}
else -> throw FatalAstException("weird dt")
}
val name = "p8p_exprvar_${count}_${type.toString().lowercase()}"
var subVars = newVariables[scope]
if(subVars==null) {
subVars = mutableListOf()
@ -442,21 +462,21 @@ private fun transformNewExpressions(program: PtProgram) {
return PtIdentifier("${scope.scopedName}.$name", type, pos)
}
fun transformExpr(expr: PtBinaryExpression, postfix: String, depth: Int): Pair<PtExpression, List<IPtAssignment>> {
fun transformExpr(expr: PtBinaryExpression): Pair<PtExpression, List<IPtAssignment>> {
// depth first process the expression tree
val scope = expr.definingSub()!!
val assignments = mutableListOf<IPtAssignment>()
fun transformOperand(node: PtExpression, kind: String): PtNode {
fun transformOperand(node: PtExpression): PtNode {
return when(node) {
is PtNumber, is PtIdentifier, is PtArray, is PtString, is PtMachineRegister -> node
is PtBinaryExpression -> {
val (replacement, subAssigns) = transformExpr(node, kind, depth+1)
val (replacement, subAssigns) = transformExpr(node)
assignments.addAll(subAssigns)
replacement
}
else -> {
val variable = getExprVar(kind, node.type, depth, node.position, scope)
val variable = getExprVar(node.type, node.position, scope)
val assign = PtAssignment(node.position)
val target = PtAssignTarget(variable.position)
target.add(variable)
@ -468,26 +488,26 @@ private fun transformNewExpressions(program: PtProgram) {
}
}
val newLeft = transformOperand(expr.left,"l")
val newRight = transformOperand(expr.right, "r")
val newLeft = transformOperand(expr.left)
val newRight = transformOperand(expr.right)
// process the binexpr
val resultVar =
if(expr.type == expr.left.type) {
getExprVar(postfix, expr.type, depth, expr.position, scope)
getExprVar(expr.type, expr.position, scope)
} else {
if(expr.operator in ComparisonOperators && expr.type in ByteDatatypes) {
// this is very common and should be dealth with correctly; byte==0, word>42
val varType = if(expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type
getExprVar(postfix, varType, depth, expr.position, scope)
getExprVar(varType, expr.position, scope)
}
else if(expr.left.type in PassByReferenceDatatypes && expr.type==DataType.UBYTE) {
// this is common and should be dealth with correctly; for instance "name"=="john"
val varType = if (expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type
getExprVar(postfix, varType, depth, expr.position, scope)
getExprVar(varType, expr.position, scope)
} else if(expr.left.type equalsSize expr.type) {
getExprVar(postfix, expr.type, depth, expr.position, scope)
getExprVar(expr.type, expr.position, scope)
} else {
TODO("expression type differs from left operand type! got ${expr.left.type} expected ${expr.type} ${expr.position}")
}
@ -539,12 +559,13 @@ private fun transformNewExpressions(program: PtProgram) {
}
}
fun transform(node: PtNode, parent: PtNode, depth: Int) {
fun transform(node: PtNode, parent: PtNode) {
if(node is PtBinaryExpression) {
println("BINEXPR AT ${node.position}")
node.children.toTypedArray().forEach {
transform(it, node, depth+1)
transform(it, node)
}
val (rep, assignments) = transformExpr(node, "l", depth)
val (rep, assignments) = transformExpr(node)
var replacement = rep
if(!(rep.type equalsSize node.type)) {
if(rep.type in NumericDatatypes && node.type in ByteDatatypes) {
@ -565,13 +586,13 @@ private fun transformNewExpressions(program: PtProgram) {
stmt.parent.add(idx, it as PtNode)
}
} else {
node.children.toTypedArray().forEach { child -> transform(child, node, depth+1) }
node.children.toTypedArray().forEach { child -> transform(child, node) }
}
}
program.allBlocks().forEach { block ->
block.children.toTypedArray().forEach {
transform(it, block, 0)
transform(it, block)
}
}

View File

@ -19,9 +19,9 @@ main {
txt.print("name2 fail!\n")
}
if name=="aaa" or name=="john" or name=="bbb" ; TODO fix this result on C64 target, no newexpr!
if name=="aaa" or name=="john" or name=="bbb"
txt.print("name1b ok\n")
if name=="aaa" or name=="zzz" or name=="bbb" ; TODO fix this result on C64 target, no newexpr!
if name=="aaa" or name=="zzz" or name=="bbb"
txt.print("name2b fail!\n")