void CallNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { // // Compute the type of a function call. This is the same type // as the function's return type, provided the call is valid. // // // Verify that what we are trying to call is actually a function. // if (!function) return; function->computeType (lcontext, initInfo); if (!function->type) return; FunctionTypePtr functionType = function->type.cast <FunctionType>(); if (!functionType) { MESSAGE_LE (lcontext, ERR_NON_FUNC, function->lineNumber, "Invalid function call to call non-function " "(" << function->name << " is of type " << function->type->asString() << ")."); return; } // // We shouldn't have more function call arguments than parameters. // const ParamVector ¶meters = functionType->parameters(); if (arguments.size() > parameters.size()) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM, function->lineNumber, "Too many arguments in call to function " << function->name << "."); return; } // // Compare the types of the arguments to the call with // the types of the function's parameters. // for (int i = 0; i < (int)parameters.size(); ++i) { if (i < (int)arguments.size()) { // // We have a function call argument for parameter i. // arguments[i]->computeType (lcontext, initInfo); TypePtr argType = arguments[i]->type; if (!argType) return; DataTypePtr paramType = parameters[i].type; if (parameters[i].isWritable()) { // // output parameter -- argument must be an lvalue // of the same type as the parameter // if (!arguments[i]->isLvalue (initInfo)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_LVAL, arguments[i]->lineNumber, "Argument " << i+1 << " in call to function " << function->name << " corresponds to an output " "parameter but it is not an lvalue."); return; } if (!paramType->isSameTypeAs (argType)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_TYPE, arguments[i]->lineNumber, "Type of argument " << i+1 << " in call to " "function " << function->name << " is not the " "same as the type of the function's parameter " "(" << argType->asString() << " value " "for " << paramType->asString() << " parameter.)"); return; } } else { // // input parameter -- it must be possible to cast // the argument type to the parameter type // if (!paramType->canCastFrom (argType)) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_TYPE, arguments[i]->lineNumber, "Cannot convert the type of argument " << i+1 << " " "in call to function " << function->name << " " "to the type of the function's parameter " "(" << argType->asString() << " value " "for " << paramType->asString() << " parameter.)"); return; } } } else { // // We have no function call argument for parameter i. // The parameter must have a default value. // if (!parameters[i].defaultValue) { MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM, function->lineNumber, "Not enough arguments in call to " "function " << function->name << "."); return; } } } // // If we get here, then the call is valid. // type = functionType->returnType(); }