diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 6e5423fd6..68a1dd9f3 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -810,6 +810,10 @@ internal class AstChecker(private val program: Program, errors.warn("sgn() of unsigned type is always 0 or 1, this is perhaps not what was intended", functionCall.args.first().position) } + val error = VerifyFunctionArgTypes.checkTypes(functionCall, functionCall.definingScope(), program) + if(error!=null) + errors.err(error, functionCall.args.first().position) + super.visit(functionCall) } @@ -838,6 +842,11 @@ internal class AstChecker(private val program: Program, errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position) } } + + val error = VerifyFunctionArgTypes.checkTypes(functionCallStatement, functionCallStatement.definingScope(), program) + if(error!=null) + errors.err(error, functionCallStatement.args.first().position) + super.visit(functionCallStatement) } diff --git a/compiler/src/prog8/ast/processing/VerifyFunctionArgTypes.kt b/compiler/src/prog8/ast/processing/VerifyFunctionArgTypes.kt index cf6c09d2c..58f5778a6 100644 --- a/compiler/src/prog8/ast/processing/VerifyFunctionArgTypes.kt +++ b/compiler/src/prog8/ast/processing/VerifyFunctionArgTypes.kt @@ -13,30 +13,41 @@ import prog8.functions.BuiltinFunctions class VerifyFunctionArgTypes(val program: Program) : IAstVisitor { - override fun visit(functionCall: FunctionCall) - = checkTypes(functionCall as IFunctionCall, functionCall.definingScope()) + override fun visit(functionCall: FunctionCall) { + val error = checkTypes(functionCall as IFunctionCall, functionCall.definingScope(), program) + if(error!=null) + throw CompilerException(error) + } - override fun visit(functionCallStatement: FunctionCallStatement) - = checkTypes(functionCallStatement as IFunctionCall, functionCallStatement.definingScope()) + override fun visit(functionCallStatement: FunctionCallStatement) { + val error = checkTypes(functionCallStatement as IFunctionCall, functionCallStatement.definingScope(), program) + if (error!=null) + throw CompilerException(error) + } - private fun checkTypes(call: IFunctionCall, scope: INameScope) { - val argtypes = call.args.map { it.inferType(program).typeOrElse(DataType.STRUCT) } - val target = call.target.targetStatement(scope) - when(target) { - is Subroutine -> { - val paramtypes = target.parameters.map { it.type } - if(argtypes!=paramtypes) - throw CompilerException("parameter type mismatch $call") - } - is BuiltinFunctionStatementPlaceholder -> { - val func = BuiltinFunctions.getValue(target.name) - val paramtypes = func.parameters.map { it.possibleDatatypes } - for(x in argtypes.zip(paramtypes)) { - if(x.first !in x.second) - throw CompilerException("parameter type mismatch $call") + companion object { + fun checkTypes(call: IFunctionCall, scope: INameScope, program: Program): String? { + val argtypes = call.args.map { it.inferType(program).typeOrElse(DataType.STRUCT) } + val target = call.target.targetStatement(scope) + when (target) { + is Subroutine -> { + val paramtypes = target.parameters.map { it.type } + val mismatch = argtypes.zip(paramtypes).indexOfFirst { it.first != it.second} + if(mismatch>=0) + return "argument ${mismatch+1} type mismatch" + } + is BuiltinFunctionStatementPlaceholder -> { + val func = BuiltinFunctions.getValue(target.name) + val paramtypes = func.parameters.map { it.possibleDatatypes } + for (x in argtypes.zip(paramtypes).withIndex()) { + if (x.value.first !in x.value.second) + return "argument ${x.index+1} type mismatch" + } + } + else -> { } } - else -> {} + return null } } } diff --git a/examples/test.p8 b/examples/test.p8 index e1e58af83..5bda70f0a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -16,9 +16,7 @@ main { } sub wot(uword text) { - ;c64scr.print(text) ; TODO better type error - ;c64.CHROUT('\n') - c64scr.print_uwhex(text, 1) + c64scr.print(4.4, 1) c64.CHROUT('\n') } }