/** Find function (also processes arguments) */
const Function& FunctionTable::findFunction(const std::string& name, const std::vector<Argument>& args, bool once) const
{
    
    std::pair<std::multimap<std::string, Function *>::const_iterator,
              std::multimap<std::string, Function *>::const_iterator> retVal;
    
    size_t hits = count(name);
    if (hits == 0)
    {
        
        if (parentTable != NULL) 
        {
            // \TODO: We shouldn't allow const casts!!!
            FunctionTable* pt = const_cast<FunctionTable*>(parentTable);
            return pt->findFunction(name, args, once);
        }
        else
        {
            throw RbException("No function named '"+ name + "'");
        }
        
    }
    retVal = equal_range(name);
    if (hits == 1)
    {
        if (retVal.first->second->checkArguments(args,NULL,once) == false)
        {
            std::ostringstream msg;

            msg << "Argument or label mismatch for function call '" << name << "' with arguments (";

            // print the passed arguments
            for (std::vector<Argument>::const_iterator it = args.begin(); it != args.end(); it++) 
            {
                // add a comma before the every argument except the first
                if (it != args.begin()) 
                {
                    msg << ",";
                }
                
                // create the default type of the passed-in argument
                std::string type = "NULL";
                // get the type if the variable wasn't NULL
                if (it->getVariable() != NULL)
                {
                    type = it->getVariable()->getRevObject().getType();
                }
                msg << " " << type;
                
                // create the default DAG type of the passed-in argument
                std::string dagtype = "";
                // get the type if the variable wasn't NULL
                if (it->getVariable() != NULL && it->getVariable()->getRevObject().getDagNode() != NULL )
                {
                    if ( it->getVariable()->getRevObject().getDagNode()->getDagNodeType() == RevBayesCore::DagNode::DETERMINISTIC )
                    {
                        dagtype = "<deterministic>";
                    }
                    else if ( it->getVariable()->getRevObject().getDagNode()->getDagNodeType() == RevBayesCore::DagNode::STOCHASTIC )
                    {
                        dagtype = "<stochastic>";
                    }
                    else if ( it->getVariable()->getRevObject().getDagNode()->getDagNodeType() == RevBayesCore::DagNode::CONSTANT )
                    {
                        dagtype = "<constant>";
                    }
                    else
                    {
                        dagtype = "<?>";
                    }
                }
                msg << dagtype;
                
                if ( it->getLabel() != "" )
                {
                    msg << " '" << it->getLabel() << "'";
                }
            }
            msg << " )." << std::endl;
            msg << "Correct usage is:" << std::endl;
            retVal.first->second->printValue( msg );
            msg << std::endl;
            throw RbException( msg );
        }
        return *retVal.first->second;
    }
    else 
    {
        std::vector<double>* matchScore = new std::vector<double>();
        std::vector<double> bestScore;
        Function* bestMatch = NULL;

        bool ambiguous = false;
        std::multimap<std::string, Function *>::const_iterator it;
        for (it=retVal.first; it!=retVal.second; it++) 
        {
            matchScore->clear();
            if ( (*it).second->checkArguments(args, matchScore, once) == true )
            {
                if ( bestMatch == NULL ) 
                {
                    bestScore = *matchScore;
                    bestMatch = it->second;
                    ambiguous = false;
                }
                else 
                {
                    size_t j;
                    for (j=0; j<matchScore->size() && j<bestScore.size(); j++) 
                    {
                        if ((*matchScore)[j] < bestScore[j]) 
                        {
                            bestScore = *matchScore;
                            bestMatch = it->second;
                            ambiguous = false;
                            break;
                        }
                        else if ((*matchScore)[j] > bestScore[j])
                            break;
                    }
                    if (j==matchScore->size() || j==bestScore.size()) 
                    {
                        ambiguous = true;   // Continue checking, there might be better matches ahead
                    }
                }
            }
        }
        
        // free the memory
        delete matchScore;
        
        /* Delete all processed arguments except those of the best matching function, if it is ambiguous */
        for ( it = retVal.first; it != retVal.second; it++ ) 
        {
            if ( !( (*it).second == bestMatch && ambiguous == false ) )
                (*it).second->clear();
        }
        if ( bestMatch == NULL || ambiguous == true ) 
        {
            std::ostringstream msg;
            if ( bestMatch == NULL )
                msg << "No overloaded function '" << name << "' matches for arguments (";
            else
                msg << "Ambiguous call to function '" << name << "' with arguments (";
            // print the passed arguments
            for (std::vector<Argument>::const_iterator j = args.begin(); j != args.end(); j++) 
            {
                if (j != args.begin()) 
                {
                    msg << ",";
                }
                const RevPtr<const RevVariable>& theVar = j->getVariable();
                msg << " " << theVar->getRevObject().getTypeSpec().getType();
                
            }
            msg << " )" << std::endl;
            
            msg << "Potentially matching functions are:" << std::endl;
            for ( it = retVal.first; it != retVal.second; it++ ) 
            {
                (*it).second->printValue( msg );
                msg << std::endl;
            }
            throw RbException( msg );
        }
        else 
        {
            return *bestMatch;
        }
    }
    
}
Exemple #2
0
/** Find function (also processes arguments) */
Function& FunctionTable::findFunction(const std::string& name, const std::vector<Argument>& args) {
    
    std::pair<std::multimap<std::string, Function *>::iterator,
              std::multimap<std::string, Function *>::iterator> retVal;
    
    size_t hits = count(name);
    if (hits == 0)
    {
        
        if (parentTable != NULL) 
        {
            // \TODO: We shouldn't allow const casts!!!
            FunctionTable* pt = const_cast<FunctionTable*>(parentTable);
            return pt->findFunction(name, args);
        }
        else
        {
            throw RbException("No function named '"+ name + "'");
        }
        
    }
    retVal = equal_range(name);
    if (hits == 1) {
        if (retVal.first->second->checkArguments(args,NULL) == false) 
        {
            
            std::ostringstream msg;
            msg << "Argument mismatch for call to function '" << name << "'(";
            // print the passed arguments
            for (std::vector<Argument>::const_iterator it = args.begin(); it != args.end(); it++) 
            {
                if (it != args.begin()) 
                {
                    msg << ",";
                }
                std::string type = "NULL";
                if (it->getVariable() != NULL) type = it->getVariable()->getRevObject().getType();
                msg << " " << type << " \"" << it->getLabel() << "\"";
            }
            msg << " ). Correct usage is:" << std::endl;
            retVal.first->second->printValue( msg );
            msg << std::endl;
            throw RbException( msg );
        }
        return *retVal.first->second;
    }
    else 
    {
        std::vector<unsigned int>* matchScore = new std::vector<unsigned int>();
        std::vector<unsigned int> bestScore;
        Function* bestMatch = NULL;

        bool ambiguous = false;
        std::multimap<std::string, Function *>::iterator it;
        for (it=retVal.first; it!=retVal.second; it++) 
        {
            matchScore->clear();
            if ( (*it).second->checkArguments(args, matchScore) == true ) 
            {
                if ( bestMatch == NULL ) 
                {
                    bestScore = *matchScore;
                    bestMatch = it->second;
                    ambiguous = false;
                }
                else 
                {
                    size_t j;
                    for (j=0; j<matchScore->size() && j<bestScore.size(); j++) 
                    {
                        if ((*matchScore)[j] < bestScore[j]) 
                        {
                            bestScore = *matchScore;
                            bestMatch = it->second;
                            ambiguous = false;
                            break;
                        }
                        else if ((*matchScore)[j] > bestScore[j])
                            break;
                    }
                    if (j==matchScore->size() || j==bestScore.size()) 
                    {
                        ambiguous = true;   // Continue checking, there might be better matches ahead
                    }
                }
            }
        }
        
        // free the memory
        delete matchScore;
        
        /* Delete all processed arguments except those of the best matching function, if it is ambiguous */
        for ( it = retVal.first; it != retVal.second; it++ ) 
        {
            if ( !( (*it).second == bestMatch && ambiguous == false ) )
                (*it).second->clear();
        }
        if ( bestMatch == NULL || ambiguous == true ) 
        {
            std::ostringstream msg;
            if ( bestMatch == NULL )
                msg << "No overloaded function '" << name << "' matches for arguments (";
            else
                msg << "Ambiguous call to function '" << name << "' with arguments (";
            // print the passed arguments
            for (std::vector<Argument>::const_iterator j = args.begin(); j != args.end(); j++) 
            {
                if (j != args.begin()) 
                {
                    msg << ",";
                }
//                msg << " " << it->getVariable().getDagNode()->getValue().getTypeSpec();
                const RevPtr<const Variable>& theVar = j->getVariable();
                msg << " " << theVar->getRevObject().getTypeSpec().getType();
                
            }
            msg << " )" << std::endl;
            
            msg << "Potentially matching functions are:" << std::endl;
            for ( it = retVal.first; it != retVal.second; it++ ) 
            {
                (*it).second->printValue( msg );
                msg << std::endl;
            }
            throw RbException( msg );
        }
        else 
        {
            return *bestMatch;
        }
    }
    
}