From 4ade45f51f62106375745539152d3acf8f1ab41d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 11 Nov 2018 18:19:08 +0100 Subject: [PATCH] tweaking subroutine return values --- compiler/examples/test.p8 | 12 ++++++++++++ compiler/src/prog8/ast/AST.kt | 3 ++- compiler/src/prog8/ast/AstChecker.kt | 17 ++++++++++++----- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index a414c9b45..50d3007ed 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -7,7 +7,19 @@ sub start() { + ubyte derp + + + derp=foo() + derp=c64.GETADR() return } + +sub foo() -> ubyte { + return 1 ; @todo not ubyte but byte (if sub returns byte) +} + + + } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 8c1363d28..badb63f7f 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -1380,7 +1380,7 @@ class FunctionCall(override var target: IdentifierReference, return null // no return value if(stmt.returntypes.size==1) return stmt.returntypes[0] - return null // has multiple return types... + return null // has multiple return types... so not a single resulting datatype possible } is Label -> return null } @@ -1447,6 +1447,7 @@ class AnonymousScope(override var statements: MutableList, // the subroutine class covers both the normal user-defined subroutines, // and also the predefined/ROM/register-based subroutines. +// (multiple return types can only occur for the latter type) class Subroutine(override val name: String, val parameters: List, val returntypes: List, diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 0c81194ad..0b5eb17f2 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -196,8 +196,9 @@ class AstChecker(private val namespace: INameScope, super.process(subroutine) // user-defined subroutines can only have zero or one return type + // (multiple return values are only allowed for asm subs) if(!subroutine.isAsmSubroutine && subroutine.returntypes.size>1) - err("subroutine has more than one return value") + err("subroutines can only have one return value") // subroutine must contain at least one 'return' or 'goto' // (or if it has an asm block, that must contain a 'rts' or 'jmp') @@ -357,8 +358,15 @@ class AstChecker(private val namespace: INameScope, } else { val sourceDatatype: DataType? = assignment.value.resultingDatatype(namespace, heap) if(sourceDatatype==null) { - if(assignment.value is FunctionCall) - checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position)) + if(assignment.value is FunctionCall) { + // a functioncall COULD return multiple values (from an asm subroutine), treat that differently + val stmt = (assignment.value as FunctionCall).target.targetStatement(namespace) + if(stmt is Subroutine && stmt.returntypes.size>1) { + checkResult.add(ExpressionError("subroutine returning multiple values", assignment.value.position)) // TODO check this + } + else + checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position)) + } else checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position)) } @@ -633,8 +641,7 @@ class AstChecker(private val namespace: INameScope, if(targetStatement!=null) checkFunctionCall(targetStatement, functionCall.arglist, functionCall.position) if(targetStatement is Subroutine && targetStatement.returntypes.isNotEmpty()) - if(!targetStatement.isAsmSubroutine) - printWarning("result value of subroutine call is discarded", functionCall.position) + printWarning("result value of subroutine call is discarded", functionCall.position) return super.process(functionCall) }