fix bool param lookup problem

This commit is contained in:
Irmen de Jong 2022-07-07 22:09:04 +02:00
parent bdb7de34be
commit 1163543a98
7 changed files with 63 additions and 27 deletions

View File

@ -159,7 +159,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
}
argOrder.forEach {
val param = callee.parameters[it]
val targetVar = callee.searchAsmParameter(param.name)!!
val targetVar = callee.searchParameter(param.name)!!
asmgen.popCpuStack(param.type, targetVar, (call as Node).definingSubroutine)
}
}

View File

@ -55,9 +55,10 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
return Pair("invalid number of arguments", call.position)
val mismatch = argtypes.zip(consideredParamTypes).indexOfFirst { !argTypeCompatible(it.first, it.second) }
if(mismatch>=0) {
val actual = argtypes[mismatch].toString()
val expected = consideredParamTypes[mismatch].toString()
return Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
val actual = argtypes[mismatch]
val expected = consideredParamTypes[mismatch]
if(expected==DataType.BOOL && actual==DataType.UBYTE && call.args[mismatch].constValue(program)?.number !in setOf(0.0, 1.0))
return Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
}
if(target.isAsmSubroutine) {
if(target.asmReturnvaluesRegisters.size>1) {
@ -85,9 +86,9 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
argtypes.zip(consideredParamTypes).forEachIndexed { index, pair ->
val anyCompatible = pair.second.any { argTypeCompatible(pair.first, it) }
if (!anyCompatible) {
val actual = pair.first.toString()
val actual = pair.first
return if(pair.second.size==1) {
val expected = pair.second[0].toString()
val expected = pair.second[0]
Pair("argument ${index + 1} type mismatch, was: $actual expected: $expected", call.args[index].position)
} else {
val expected = pair.second.toList().toString()

View File

@ -7,15 +7,54 @@ import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.types.instanceOf
import prog8.ast.IFunctionCall
import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.*
import prog8.ast.statements.Assignment
import prog8.ast.statements.IfElse
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8.compiler.printProgram
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText
class TestTypecasts: FunSpec({
test("correct handling of bool parameters") {
val text="""
main {
sub thing(bool b1, bool b2) -> bool {
return (b1 and b2) or b1
}
sub start() {
bool boolvalue1 = true
bool boolvalue2 = false
uword xx
boolvalue1 = thing(true, false)
boolvalue2 = thing(xx, xx)
if boolvalue1 and boolvalue2
boolvalue1=false
}
}"""
val result = compileText(C64Target(), false, text, writeAssembly = false)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 9
val fcall1 = ((stmts[6] as Assignment).value as IFunctionCall)
fcall1.args[0] shouldBe NumericLiteral(DataType.UBYTE, 1.0, Position.DUMMY)
fcall1.args[1] shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
val fcall2 = ((stmts[7] as Assignment).value as IFunctionCall)
(fcall2.args[0] as TypecastExpression).type shouldBe DataType.BOOL
(fcall2.args[1] as TypecastExpression).type shouldBe DataType.BOOL
val ifCond = (stmts[8] as IfElse).condition as BinaryExpression
ifCond.operator shouldBe "&"
(ifCond.left as IdentifierReference).nameInSource shouldBe listOf("boolvalue1")
(ifCond.right as IdentifierReference).nameInSource shouldBe listOf("boolvalue2")
}
test("correct evaluation of words in boolean expressions") {
val text="""
main {

View File

@ -77,7 +77,7 @@ interface IStatementContainer {
fun searchSymbol(name: String): Statement? {
if(this is Subroutine && isAsmSubroutine)
return searchAsmParameter(name)
return searchParameter(name)
// this is called quite a lot and could perhaps be optimized a bit more,
// but adding a memoization cache didn't make much of a practical runtime difference...
@ -138,6 +138,10 @@ interface IStatementContainer {
}
}
}
if(this is Subroutine && !isAsmSubroutine)
return searchParameter(name)
return null
}

View File

@ -770,9 +770,7 @@ class Subroutine(override val name: String,
// code to provide the ability to reference asmsub parameters via qualified name:
private val asmParamsDecls = mutableMapOf<String, VarDecl>()
fun searchAsmParameter(name: String): VarDecl? {
require(isAsmSubroutine)
fun searchParameter(name: String): VarDecl? {
val existingDecl = asmParamsDecls[name]
if(existingDecl!=null)
return existingDecl

View File

@ -5,9 +5,6 @@ For next release
^^^^^^^^^^^^^^^^
- add ARRAY_OF_BOOL array type
- test various scenarios of using bool type vs byte actually produces tighter code
make unit test of them?
...

View File

@ -3,22 +3,19 @@
main {
bool boolvalue1 = true
bool boolvalue2 = false
ubyte @shared ubvalue1 = true
ubyte @shared ubvalue2 = false
sub thing(bool b1, bool b2) -> bool {
return b1 and b2
return (b1 and b2) or b1
}
sub start() {
bool boolvalue1 = true
bool boolvalue2 = false
uword xx
ubvalue1 = boolvalue1 & 1
ubvalue2 = 1 & boolvalue1
ubvalue1 = boolvalue1 & 0
ubvalue2 = boolvalue1 & 8
boolvalue1 = boolvalue2 & 1 ==0
; boolvar & 1 -> boolvar, (boolvar & 1 == 0) -> not boolvar
boolvalue1 = thing(true, false)
boolvalue2 = thing(xx, xx)
if boolvalue1 and boolvalue2
boolvalue1=false
}
}