From 731132d4b3f0f6d11a48fa550b1151e82dc2dcad Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 5 Apr 2024 02:13:31 +0200 Subject: [PATCH] check number of result values in return statements --- .../prog8/compiler/astprocessing/AstChecker.kt | 4 +--- .../astprocessing/VerifyFunctionArgTypes.kt | 10 ++-------- .../src/prog8/ast/expressions/AstExpressions.kt | 16 ---------------- docs/source/todo.rst | 2 +- examples/c64/plasma.p8 | 5 +++-- examples/cx16/chunkedfile/demo.p8 | 3 ++- examples/cx16/chunkedfile/mcf.p8 | 15 ++++++++++----- examples/cx16/plasma.p8 | 5 +++-- examples/test.p8 | 6 ------ 9 files changed, 22 insertions(+), 44 deletions(-) diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 892792cb2..33aa7c2dd 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -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. diff --git a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt index cd770c3c4..63f8cd1cb 100644 --- a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt +++ b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt @@ -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) } } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 44c7431d3..b0cbccaa2 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -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() diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 5d37ebe87..37bc1e701 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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) diff --git a/examples/c64/plasma.p8 b/examples/c64/plasma.p8 index b6dfcfa8f..97dc56e26 100644 --- a/examples/c64/plasma.p8 +++ b/examples/c64/plasma.p8 @@ -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() diff --git a/examples/cx16/chunkedfile/demo.p8 b/examples/cx16/chunkedfile/demo.p8 index 9c9740532..bc1d6a889 100644 --- a/examples/cx16/chunkedfile/demo.p8 +++ b/examples/cx16/chunkedfile/demo.p8 @@ -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) diff --git a/examples/cx16/chunkedfile/mcf.p8 b/examples/cx16/chunkedfile/mcf.p8 index e264e4390..710978439 100644 --- a/examples/cx16/chunkedfile/mcf.p8 +++ b/examples/cx16/chunkedfile/mcf.p8 @@ -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 } } diff --git a/examples/cx16/plasma.p8 b/examples/cx16/plasma.p8 index a156ba7ef..a3436db14 100644 --- a/examples/cx16/plasma.p8 +++ b/examples/cx16/plasma.p8 @@ -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() diff --git a/examples/test.p8 b/examples/test.p8 index 57f33969e..4ff59cba6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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) } }