mirror of
https://github.com/irmen/prog8.git
synced 2024-06-17 04:29:44 +00:00
check number of result values in return statements
This commit is contained in:
parent
98acff802f
commit
731132d4b3
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
%import diskio
|
||||
%import textio
|
||||
%import mcf
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user