mirror of
https://github.com/irmen/prog8.git
synced 2024-10-07 15:57:03 +00:00
fix bool param lookup problem
This commit is contained in:
parent
bdb7de34be
commit
1163543a98
@ -159,7 +159,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
}
|
}
|
||||||
argOrder.forEach {
|
argOrder.forEach {
|
||||||
val param = callee.parameters[it]
|
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)
|
asmgen.popCpuStack(param.type, targetVar, (call as Node).definingSubroutine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,10 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
return Pair("invalid number of arguments", call.position)
|
return Pair("invalid number of arguments", call.position)
|
||||||
val mismatch = argtypes.zip(consideredParamTypes).indexOfFirst { !argTypeCompatible(it.first, it.second) }
|
val mismatch = argtypes.zip(consideredParamTypes).indexOfFirst { !argTypeCompatible(it.first, it.second) }
|
||||||
if(mismatch>=0) {
|
if(mismatch>=0) {
|
||||||
val actual = argtypes[mismatch].toString()
|
val actual = argtypes[mismatch]
|
||||||
val expected = consideredParamTypes[mismatch].toString()
|
val expected = consideredParamTypes[mismatch]
|
||||||
return Pair("argument ${mismatch + 1} type mismatch, was: $actual expected: $expected", call.args[mismatch].position)
|
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.isAsmSubroutine) {
|
||||||
if(target.asmReturnvaluesRegisters.size>1) {
|
if(target.asmReturnvaluesRegisters.size>1) {
|
||||||
@ -85,9 +86,9 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
argtypes.zip(consideredParamTypes).forEachIndexed { index, pair ->
|
argtypes.zip(consideredParamTypes).forEachIndexed { index, pair ->
|
||||||
val anyCompatible = pair.second.any { argTypeCompatible(pair.first, it) }
|
val anyCompatible = pair.second.any { argTypeCompatible(pair.first, it) }
|
||||||
if (!anyCompatible) {
|
if (!anyCompatible) {
|
||||||
val actual = pair.first.toString()
|
val actual = pair.first
|
||||||
return if(pair.second.size==1) {
|
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)
|
Pair("argument ${index + 1} type mismatch, was: $actual expected: $expected", call.args[index].position)
|
||||||
} else {
|
} else {
|
||||||
val expected = pair.second.toList().toString()
|
val expected = pair.second.toList().toString()
|
||||||
|
@ -7,15 +7,54 @@ import io.kotest.matchers.shouldNotBe
|
|||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import io.kotest.matchers.types.instanceOf
|
import io.kotest.matchers.types.instanceOf
|
||||||
import prog8.ast.IFunctionCall
|
import prog8.ast.IFunctionCall
|
||||||
import prog8.ast.expressions.AddressOf
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.expressions.IdentifierReference
|
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.code.target.C64Target
|
||||||
|
import prog8.compiler.printProgram
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
import prog8tests.helpers.compileText
|
import prog8tests.helpers.compileText
|
||||||
|
|
||||||
|
|
||||||
class TestTypecasts: FunSpec({
|
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") {
|
test("correct evaluation of words in boolean expressions") {
|
||||||
val text="""
|
val text="""
|
||||||
main {
|
main {
|
||||||
|
@ -77,7 +77,7 @@ interface IStatementContainer {
|
|||||||
|
|
||||||
fun searchSymbol(name: String): Statement? {
|
fun searchSymbol(name: String): Statement? {
|
||||||
if(this is Subroutine && isAsmSubroutine)
|
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,
|
// 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...
|
// 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,9 +770,7 @@ class Subroutine(override val name: String,
|
|||||||
// code to provide the ability to reference asmsub parameters via qualified name:
|
// code to provide the ability to reference asmsub parameters via qualified name:
|
||||||
private val asmParamsDecls = mutableMapOf<String, VarDecl>()
|
private val asmParamsDecls = mutableMapOf<String, VarDecl>()
|
||||||
|
|
||||||
fun searchAsmParameter(name: String): VarDecl? {
|
fun searchParameter(name: String): VarDecl? {
|
||||||
require(isAsmSubroutine)
|
|
||||||
|
|
||||||
val existingDecl = asmParamsDecls[name]
|
val existingDecl = asmParamsDecls[name]
|
||||||
if(existingDecl!=null)
|
if(existingDecl!=null)
|
||||||
return existingDecl
|
return existingDecl
|
||||||
|
@ -5,9 +5,6 @@ For next release
|
|||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- add ARRAY_OF_BOOL array type
|
- add ARRAY_OF_BOOL array type
|
||||||
|
|
||||||
- test various scenarios of using bool type vs byte actually produces tighter code
|
|
||||||
make unit test of them?
|
|
||||||
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -3,22 +3,19 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
bool boolvalue1 = true
|
|
||||||
bool boolvalue2 = false
|
|
||||||
ubyte @shared ubvalue1 = true
|
|
||||||
ubyte @shared ubvalue2 = false
|
|
||||||
|
|
||||||
sub thing(bool b1, bool b2) -> bool {
|
sub thing(bool b1, bool b2) -> bool {
|
||||||
return b1 and b2
|
return (b1 and b2) or b1
|
||||||
}
|
}
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
bool boolvalue1 = true
|
||||||
|
bool boolvalue2 = false
|
||||||
|
uword xx
|
||||||
|
|
||||||
ubvalue1 = boolvalue1 & 1
|
boolvalue1 = thing(true, false)
|
||||||
ubvalue2 = 1 & boolvalue1
|
boolvalue2 = thing(xx, xx)
|
||||||
ubvalue1 = boolvalue1 & 0
|
|
||||||
ubvalue2 = boolvalue1 & 8
|
if boolvalue1 and boolvalue2
|
||||||
boolvalue1 = boolvalue2 & 1 ==0
|
boolvalue1=false
|
||||||
; boolvar & 1 -> boolvar, (boolvar & 1 == 0) -> not boolvar
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user