check number of result values in return statements

This commit is contained in:
Irmen de Jong 2024-04-05 02:13:31 +02:00
parent 98acff802f
commit 731132d4b3
9 changed files with 22 additions and 44 deletions

View File

@ -130,9 +130,7 @@ internal class AstChecker(private val program: Program,
}
if(expectedReturnValues.size==1 && returnStmt.value!=null) {
val valueDt = returnStmt.value!!.inferType(program)
if(!valueDt.isKnown) {
errors.err("return value type mismatch or unknown symbol", returnStmt.value!!.position)
} else {
if(valueDt.isKnown) {
if (expectedReturnValues[0] != valueDt.getOr(DataType.UNDEFINED)) {
if(valueDt istype DataType.BOOL && expectedReturnValues[0] == DataType.UBYTE) {
// if the return value is a bool and the return type is ubyte, allow this. But give a warning.

View File

@ -114,12 +114,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
}
if(target.isAsmSubroutine) {
if(target.asmReturnvaluesRegisters.size>1) {
// multiple return values will NOT work inside an expression.
// they MIGHT work in a regular assignment or just a function call statement.
// EXCEPTION:
// if the asmsub returns multiple values and one of them is via a status register bit (such as carry),
// it *is* possible to handle them by just actually assigning the register value and
// dealing with the status bit as just being that, the status bit after the call.
// multiple return values will NOT work inside an expression. Use an assignment first.
val parent = if(call is Statement) call.parent else if(call is Expression) call.parent else null
if (call !is FunctionCallStatement) {
val checkParent =
@ -128,8 +123,7 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
else
parent
if (checkParent !is Assignment && checkParent !is VarDecl) {
val (returnRegisters, _) = target.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null }
if (returnRegisters.size>1) {
if (target.asmReturnvaluesRegisters.size>1) {
return Pair("can't use subroutine call that returns multiple return values here", call.position)
}
}

View File

@ -1166,22 +1166,6 @@ class FunctionCallExpression(override var target: IdentifierReference,
if(stmt.returntypes.size==1)
return InferredTypes.knownFor(stmt.returntypes[0])
// multiple return values. Can occur for asmsub routines. If there is exactly one register return value, take that.
val registerReturns = stmt.asmReturnvaluesRegisters.filter {it.registerOrPair != null }
if(registerReturns.size==1) {
return when(registerReturns.single().registerOrPair!!) {
RegisterOrPair.A,
RegisterOrPair.X,
RegisterOrPair.Y -> InferredTypes.InferredType.known(DataType.UBYTE)
RegisterOrPair.AX,
RegisterOrPair.AY,
RegisterOrPair.XY, in Cx16VirtualRegisters -> InferredTypes.InferredType.known(DataType.UWORD)
RegisterOrPair.FAC1,
RegisterOrPair.FAC2 -> InferredTypes.InferredType.known(DataType.FLOAT)
else -> throw FatalAstException("weird reg")
}
}
return InferredTypes.unknown() // has multiple return types... so not a single resulting datatype possible
}
else -> return InferredTypes.unknown()

View File

@ -1,7 +1,7 @@
TODO
====
return cx16.MACPTR(0, 2, true) -> should give compiler error about number of values
add unit test for what's now in test.p8 (multi assign stuff)
check docs on assign about status register in assignment (can no longer be ignored, use void to not assign it)

View File

@ -32,13 +32,14 @@ main {
uword frames = 0
cbm.SETTIM(0,0,0)
while cbm.GETIN()==0 {
do {
doplasma(SCREEN1)
c64.VMCSB = PAGE1
doplasma(SCREEN2)
c64.VMCSB = PAGE2
frames += 2
}
void, cx16.r0L = cbm.GETIN()
} until cx16.r0L!=0
uword jiffies = cbm.RDTIM16()

View File

@ -1,3 +1,4 @@
%import diskio
%import textio
%import mcf
@ -9,7 +10,7 @@ main {
uword duration
ubyte[256] bonkbuffer
;; diskio.fastmode(1)
;;diskio.fastmode(1)
set_screen()
cbm.SETTIM(0,0,0)

View File

@ -192,10 +192,15 @@ processchunk_call jsr $ffff ; modified
}
sub readblock(uword size, uword address, bool dontAdvance) -> uword {
if msb(size)>=2
return cx16.MACPTR(0, address, dontAdvance) ; read 512 bytes
if msb(size)!=0
return cx16.MACPTR(255, address, dontAdvance) ; read 255 bytes
return cx16.MACPTR(lsb(size), address, dontAdvance) ; read remaining number of bytes
if msb(size)>=2 {
void, cx16.r0 = cx16.MACPTR(0, address, dontAdvance) ; read 512 bytes
return cx16.r0
}
if msb(size)!=0 {
void, cx16.r0 = cx16.MACPTR(255, address, dontAdvance) ; read 255 bytes
return cx16.r0
}
void, cx16.r0 = cx16.MACPTR(lsb(size), address, dontAdvance) ; read remaining number of bytes
return cx16.r0
}
}

View File

@ -24,11 +24,12 @@ main {
uword frames = 0
cbm.SETTIM(0,0,0)
while cbm.GETIN()==0 {
do {
; sys.waitvsync()
doplasma()
frames ++
}
void, cx16.r0L = cbm.GETIN()
} until cx16.r0L!=0
uword jiffies = cbm.RDTIM16()

View File

@ -15,11 +15,5 @@ main {
void, cx16.r2, cx16.r1 = func2()
cx16.r0L = func3()
cx16.r0H = func3()
cx16.r0 = readblock()
}
sub readblock() -> uword {
return cx16.MACPTR(0, 2, true) ; TODO compiler error (number of return values)
}
}