/** Get semantic value: insert symbol and return the rhs value of the assignment */
void SyntaxStochasticAssignment::assign(RevPtr<RevVariable> &lhs, RevPtr<RevVariable> &rhs)
{
#ifdef DEBUG_PARSER
    printf( "Evaluating tilde assignment\n" );
#endif
    
    // Get distribution, which should be the return value of the rhs function
    const RevObject& exprValue = rhs->getRevObject();
    if ( !exprValue.isType( Distribution::getClassTypeSpec() ) ) 
    {
        throw RbException( "Expression on the right-hand-side of '~' did not return a distribution object." );
    }
    const Distribution &dist = dynamic_cast<const Distribution &>( exprValue );
        
    // Create new stochastic variable
    RevObject* rv = dist.createRandomVariable();
    
    // Fill the slot with the new stochastic variable
    lhs->replaceRevObject( rv );
    
    // make sure all the implicitly created variables got a correct name
    RevBayesCore::DagNode* theNode = lhs->getRevObject().getDagNode();
    theNode->setParentNamePrefix( theNode->getName() );
    
#ifdef DEBUG_PARSER
    env.printValue(std::cerr);
#endif
}
/** Get semantic value: insert symbol and return the rhs value of the assignment */
RevPtr<Variable> SyntaxDeterministicAssignment::evaluateContent( Environment& env )
{
#ifdef DEBUG_PARSER
    printf( "Evaluating deterministic assignment\n" );
#endif
    
    // Get the rhs expression wrapped and executed into a variable.
    // We need to call evaluateDynamicContent to get some elements
    // to evaluate their semantic content properly
    RevPtr<Variable> theVariable = rhsExpression->evaluateDynamicContent(env);
    
    // Get variable slot from lhs using the evaluateLHSContent to get the
    // appropriate behavior in the variable syntax element class.
    RevPtr<Variable> theSlot = lhsExpression->evaluateLHSContent( env, theVariable->getRevObject().getType() );

    // Check if the variable returned from the rhs expression is a named
    // variable in the environment. If so, we want to create an indirect
    // reference to it; otherwise, we want to fill the slot with a clone
    // of the variable returned by the rhs expression.
    if ( theVariable->getName() != "" )
        theSlot->setRevObject( theVariable->getRevObject().makeIndirectReference() );
    else
        theSlot->setRevObject( theVariable->getRevObject().clone() );
    
#ifdef DEBUG_PARSER
    env.printValue(std::cerr);
#endif    
    
    // We return the rhs variable itself as the semantic value of the
    // assignment statement. It can be used in further assignments.
    return theVariable;
}
示例#3
0
/** Get an index from an index variable in a static context */
size_t SyntaxVariable::getIndex( const RevPtr<Variable>& indexVar, Environment& env ) const
{
    if ( indexVar->getRevObject().isTypeSpec( Natural::getClassTypeSpec() ) )
    {
        // Get a Natural one-offset index
        size_t oneOffsetIndex = static_cast<Natural &>( indexVar->getRevObject() ).getValue();
        
        // Check validity
        if ( oneOffsetIndex < 1 )
        {
            std::ostringstream msg;
            msg << "Index for ";
            if ( baseVariable != NULL )
                msg << baseVariable->getFullName( env ) << ".";
            msg << identifier;
            msg << " smaller than 1";
            throw RbException( msg );
        }
        
        // Return the index
        return oneOffsetIndex;
    }
    else if ( indexVar->getRevObject().isConvertibleTo( Natural::getClassTypeSpec(), true ) )
    {
        // Convert to Natural
        RevObject* theNaturalIndex = indexVar->getRevObject().convertTo( Natural::getClassTypeSpec() );
        size_t oneOffsetIndex = static_cast<Natural*>( theNaturalIndex )->getValue();
        delete theNaturalIndex;
        
        // Check validity
        if ( oneOffsetIndex < 1 )
        {
            std::ostringstream msg;
            msg << "Index for ";
            if ( baseVariable != NULL )
                msg << baseVariable->getFullName( env ) << ".";
            msg << identifier;
            msg << " smaller than 1";
            throw RbException( msg );
        }
        
        // Return the index
        return oneOffsetIndex;
    }
    else if ( indexVar->getRevObject().isTypeSpec( RlString::getClassTypeSpec() ) )
    {
        throw RbException( "String indexes not supported (yet)");
    }
    else
    {
        std::ostringstream msg;
        msg << "Index for ";
        if ( baseVariable != NULL )
            msg << baseVariable->getFullName( env ) << ".";
        msg << identifier;
        msg << " of wrong type (neither " << Natural::getClassType() << " nor " << RlString::getClassType() << ")";
        throw RbException( msg );
    }
}
/**
 * Evaluate the content of this syntax element. This will perform a
 * subtraction assignment operation.
 */
void SyntaxSubtractionAssignment::assign(RevPtr<RevVariable> &lhs, RevPtr<RevVariable> &rhs)
{
#ifdef DEBUG_PARSER
    printf( "Evaluating subtraction assignment\n" );
#endif
    
    // Get variable from lhs. We use standard evaluation because the variable is
    // implicitly on both sides (lhs and rhs) of this type of statement
    if ( lhs == NULL )
    {
        throw RbException( "Invalid NULL variable returned by lhs expression in subtraction assignment" );
    }
    
    // Make sure that the variable is constant
    if ( !lhs->getRevObject().isConstant() )
    {
        throw RbException( "Invalid subtraction assignment to dynamic variable" );
    }
    
    // Record whether it is a workspace (control) variable
    bool isWorkspaceVar = lhs->isWorkspaceVariable();
    
    // Get a reference to the lhs value object
    const RevObject& lhs_value = lhs->getRevObject();
    
    // Evaluate the rhs expression
    if ( rhs == NULL )
    {
        throw RbException( "Invalid NULL variable returned by rhs expression in subtraction assignment" );
    }
    
    // Get a reference to the rhs value object
    const RevObject& rhs_value = rhs->getRevObject();
    
    // Generate result of the multiplication
    RevObject *newValue = lhs_value.subtract( rhs_value );
    
    // Fill the slot with the new RevVariable
    lhs->replaceRevObject( newValue );
    
    // Reset it as workspace (control) variable, if it was a workspace (control) variable before the assignment.
    // When we fill the slot, the workspace (control) variable property is reset to false by default.
    if ( isWorkspaceVar )
    {
        lhs->setWorkspaceVariableState( true );
    }
    
#ifdef DEBUG_PARSER
    env.printValue(std::cerr);
#endif
}
/**
 * Evaluate the content of this syntax element. This will perform
 * a multiplication assignment operation.
 */
RevPtr<Variable> SyntaxMultiplicationAssignment::evaluateContent( Environment& env )
{
#ifdef DEBUG_PARSER
    printf( "Evaluating multiplication assignment\n" );
#endif
    
    // Get variable from lhs. We use standard evaluation because the variable is
    // implicitly on both sides (lhs and rhs) of this type of statement
    RevPtr<Variable> theVariable = lhsExpression->evaluateContent( env );
    if ( theVariable == NULL )
        throw RbException( "Invalid NULL variable returned by lhs expression in multiplication assignment" );
    
    // Make sure that the variable is constant
    if ( !theVariable->getRevObject().isConstant() )
        throw RbException( "Invalid multiplication assignment to dynamic variable" );
    
    // Record whether it is a control variable
    bool isControlVar = theVariable->isControlVar();
    
    // Get a reference to the lhs value object
    const RevObject& lhs_value = theVariable->getRevObject();
    
    // Evaluate the rhs expression
    const RevPtr<Variable>& rhs = rhsExpression->evaluateContent( env );
    if ( rhs == NULL )
        throw RbException( "Invalid NULL variable returned by rhs expression in multiplication assignment" );
    
    // Get a reference to the rhs value object
    const RevObject& rhs_value = rhs->getRevObject();
    
    // Generate result of the multiplication
    RevObject *newValue = lhs_value.multiply( rhs_value );
    
    // Fill the slot with the new variable
    theVariable->setRevObject( newValue );
    
    // Reset it as control variable, if it was a control variable before the assignment.
    // When we fill the slot, the control variable property is reset to false by default.
    if ( isControlVar )
        theVariable->setControlVarState( true );
    
#ifdef DEBUG_PARSER
    env.printValue(std::cerr);
#endif
    
    // Return the variable for further assignment
    return theVariable;
}
/**
 * Get semantic value. When evaluating the semantic value of a reference assignment,
 * we first evaluate the rhs expression as if it were a constant expression. Among
 * other things, this makes it possible for us to create references to control
 * variables, which would be impossible if the rhs expression was evaluated as a
 * dynamic expression. We are interested in creating a reference to the variable
 * that results from evaluation of the rhs expression now.
 *
 * Note that the return variable is variable returned by the rhs expression.
 * We need not clone it.
 */
RevPtr<Variable> SyntaxReferenceAssignment::evaluateContent( Environment& env )
{
#ifdef DEBUG_PARSER
    printf( "Evaluating reference assignment\n" );
#endif
    
    // Declare variable storing the return value of the assignment expression
    RevPtr<Variable> theVariable;
    
    // Get the rhs expression wrapped and executed into a variable.
    theVariable = rhsExpression->evaluateContent( env );
    
    // Get variable slot from lhs
    RevPtr<Variable> theSlot;
    theSlot = lhsExpression->evaluateLHSContent( env, theVariable->getRevObject().getType() );
    
    // Make the slot a reference to the rhs expression variable
    theSlot->makeReference( theVariable );

#ifdef DEBUG_PARSER
    env.printValue(std::cerr);
#endif
    
    // Return variable
    return theVariable;
}
示例#7
0
/**
 * @brief Get semantic value
 * 
 * Here we evaluate the length specification (statically) and create the
 * requested variable.
 *
 */
RevPtr<RevVariable> SyntaxVariableDecl::evaluateContent( Environment& env, bool dynamic )
{
    
    // Check if variable exists
    if ( env.existsVariable( variableName ) )
        throw RbException( "Illegal attempt to redefine variable " + variableName );
    
    // Check if type exists
    if ( !Workspace::userWorkspace().existsType( elementTypeName ) )
        throw RbException( "Type '" + elementTypeName + "' does not exist" );

    // Evaluate length specification
    std::vector<size_t> lengths;
    for ( std::list<SyntaxElement*>::iterator it = lengthExpr->begin(); it != lengthExpr->end(); ++it )
    {
        if ( (*it) == NULL )
        {
            lengths.push_back( 1 );
        }
        else
        {
            RevPtr<RevVariable> temp    = (*it)->evaluateContent( env, dynamic );
            const RevObject& value   = temp->getRevObject();
            
            size_t theLength;
            if ( value.isType( Natural::getClassTypeSpec() ) )
                theLength = size_t( static_cast<const Natural&>( value ).getValue() );
            else if ( value.isConvertibleTo( Natural::getClassTypeSpec(), true ) )
            {
                RevObject* convObj = value.convertTo( Natural::getClassTypeSpec() );
                theLength = size_t( static_cast<Natural*>( convObj )->getValue() );
                delete convObj;
            }
            else
                throw RbException( "Length specification does not evaluate to an object of type 'Natural'" );
            
            if ( theLength == 0 )
                throw RbException( "Invalid length specification (0)" );
            
            lengths.push_back( theLength );
        }
    }
    
    // We ask the user workspace for the new objects
    RevObject* newObject;
    if ( lengths.size() == 0 )
        newObject = Workspace::userWorkspace().makeNewDefaultObject( elementTypeName );
    else
    {
        throw RbException("This needs replacements!!!");
//        newObject = Workspace::userWorkspace().makeNewEmptyContainer( elementTypeName, lengths.size() );
//        static_cast<Container*>( newObject )->resize( lengths );
    }

    // Add the new RevVariable
    env.addVariable( variableName, new RevVariable( newObject ) );
    
    return NULL;
}
示例#8
0
/**
 * Test if argument is valid. The boolean flag 'once' is used to signal whether the argument matching
 * is done in a static or a dynamic context. If the rule is constant, then the argument matching
 * is done in a static context (evaluate-x§once context) regardless of the setting of the once flag.
 * If the argument is constant, we try type promotion if permitted by the variable required type.
 *
 * @todo See the TODOs for fitArgument(...)
 */
bool ArgumentRule::isArgumentValid(const RevPtr<const Variable> &var, bool once) const
{
    
    if ( var == NULL )
    {
        return false;
    }
    
//    TODO: Use this code when the constant flag in ArgumentRule is used correctly
//    if ( isConstant() || !var->isAssignable() )
//    if ( isConstant() )
    if ( evalType == BY_VALUE )
    {
        once = true;
    }

    for ( std::vector<TypeSpec>::const_iterator it = argTypeSpecs.begin(); it != argTypeSpecs.end(); ++it )
    {
        if ( var->getRevObject().isTypeSpec( *it ) )
        {
            return true;
        }
        else if ( var->getRevObject().isConvertibleTo( *it, once ) )
        {
            return true;
        }
        else if ( once == false && !var->isAssignable() &&
                  var->getRevObject().isConvertibleTo( *it, true ) &&
                  (*it).isDerivedOf( var->getRevObjectTypeSpec() )
                )
        {
            return true;
        }
        
    }
    
    return false;
}
示例#9
0
double OptionRule::isArgumentValid( Argument &arg, bool once) const
{
    
    RevPtr<RevVariable> theVar = arg.getVariable();
    if ( theVar == NULL )
    {
        return -1;
    }
    
    if ( evalType == BY_VALUE || theVar->isWorkspaceVariable() || ( theVar->getRevObject().isModelObject() && theVar->getRevObject().getDagNode()->getDagNodeType() == RevBayesCore::DagNode::CONSTANT) )
    {
        once = true;
    }
    
    RlString *revObj = dynamic_cast<RlString *>( &theVar->getRevObject() );
    if ( revObj != NULL )
    {
        
        const std::string &argValue = revObj->getValue();
        for ( std::vector<std::string>::const_iterator it = options.begin(); it != options.end(); ++it)
        {
            
            if ( argValue == *it )
            {
                return 0.0;
            }
        }
        return -1;
    }
    else
    {
        return -1;
    }

    
}
示例#10
0
/**
 * This is a help function that evaluates the expression and then checks
 * whether the result is true or false, or can be interpreted as a RlBoolean
 * true or false value.
 */
bool SyntaxStatement::isTrue( SyntaxElement* expr, Environment& env ) const
{
    RevPtr<Variable> temp = expr->evaluateContent( env );
    
    if ( temp == NULL )
        return false;
    
    if ( temp->getRevObject().isTypeSpec( RlBoolean::getClassTypeSpec() ) )
    {
        bool retValue = static_cast<const RlBoolean&>( temp->getRevObject() ).getValue();
        
        return retValue;
    }
    else
    {
        RevObject *tempObject = temp->getRevObject().convertTo( RlBoolean::getClassTypeSpec() );
        RlBoolean* tempBool = static_cast<RlBoolean*>( tempObject );
        bool     retValue = tempBool->getValue();
        
        delete tempBool;
        
        return   retValue;
    }
}
示例#11
0
/**
 * Evaluate the dynamic content of the one-offset index variables.
 */
std::vector< RevPtr<Variable> > SyntaxVariable::computeDynamicIndex( Environment& env )
{
    std::vector< RevPtr<Variable> > indexVars;

    std::list<SyntaxElement*>::const_iterator it;
    for ( it = index->begin(); it != index->end(); ++it )
    {
        RevPtr<Variable> theIndex = ( *it )->evaluateDynamicContent( env );
    
        // We ensure that the variables are of type Natural or can be converted to Natural numbers.
        // No sense in checking indices against permissible range here; errors are thrown later by
        // the container or member object if we are out of range.
        if ( !theIndex->getRevObject().isTypeSpec( Natural::getClassTypeSpec() ) )
        {
            if( theIndex->getRevObject().isConstant() && theIndex->getRevObject().isConvertibleTo( Natural::getClassTypeSpec(), true ) &&
                Natural::getClassTypeSpec().isDerivedOf( theIndex->getRevObjectTypeSpec() ) )
            {
                // Type promotion
                theIndex->setRevObject( theIndex->getRevObject().convertTo( Natural::getClassTypeSpec() ) );
                theIndex->setRevObjectTypeSpec( Natural::getClassTypeSpec() );
            }
            else if ( theIndex->getRevObject().isConvertibleTo( Natural::getClassTypeSpec(), false ) )
            {
                // Dynamic type conversion
                ConverterNode<Natural>* converterNode = new ConverterNode<Natural>( "", theIndex, Natural::getClassTypeSpec() );
                theIndex = new Variable( new Natural( converterNode ) );
            }
            else
            {
                throw RbException( "No known conversion of type '" + theIndex->getRevObject().getType() + "' to 'Natural', required for index");
            }
            
        }
        
        indexVars.push_back( theIndex );
    }
    
    return indexVars;
}
示例#12
0
/**
 * Get semantic value: it is here that we execute the statement.
 *
 * @todo Return statements do not appear to be correctly handled in
 *       for loops. The return variable is discarded and the loop
 *       just continues.
 */
RevPtr<Variable> SyntaxStatement::evaluateContent(Environment& env) {

    RevPtr<Variable> result = NULL;
    
    if (statementType == For)
    {
        // Convert expression to for condition
        SyntaxForLoop* forLoop = dynamic_cast<SyntaxForLoop*>( expression );
        assert ( forLoop != NULL );

        // Initialize for loop. We use current environment for the loop variables (as in R)
        Signals::getSignals().clearFlags();
        forLoop->initializeLoop( env );

        // Now loop over statements inside the for loop
        while ( !forLoop->isFinished() )
        {
            // Get next loop state. This will update the value of the loop variable
            forLoop->getNextLoopState();

            for ( std::list<SyntaxElement*>::iterator it = statements1->begin(); it != statements1->end(); ++it )
            {
                // Get a convenient pointer to the syntax element
                SyntaxElement* theSyntaxElement = *it;
                
                // Execute statement
                result = theSyntaxElement->evaluateContent( env );

                // We do not print the result (as in R). Uncomment the code below to change this behavior

#if 0
                // Print result if it is not an assign expression (== NULL)
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && !theSyntaxElement->isAssignment() &&
                     result != NULL && result->getRevObject() != RevNullObject::getInstance())
                {
                    std::ostringstream msg;
                    result->getRevObject().printValue(msg);
                    RBOUT( msg.str() );
                }
#endif

                // Catch a return signal
                // TODO: This appears to inappropriately discard the return value of a return statement
				if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL)
                {
                    result = NULL;  // discard result
                }

                // Catch signal
                if ( !Signals::getSignals().isGood() )
                    break;
            }
            
            // Catch signals
            // TODO Return statement not handled correctly
            if ( Signals::getSignals().isSet(Signals::BREAK) )
            {
                Signals::getSignals().clearFlags();
                break;
            }
            else if ( Signals::getSignals().isSet(Signals::CONTINUE) )
            {
                Signals::getSignals().clearFlags();  // Just continue with next loop state
            }
        }
        
        // Finalize the loop (resets the forloop state for next execution round)
        forLoop->finalizeLoop();
        
    }
    else if ( statementType == Break )
    {
        // Set BREAK signal
        Signals::getSignals().set(Signals::BREAK);
    }
    else if (statementType == Next)
    {
        // Set CONTINUE signal
        Signals::getSignals().set(Signals::CONTINUE);
    }
    else if ( statementType == While )
    {
        // Loop over statements inside the while loop, first checking the expression
        while ( isTrue( expression, env ) ) {

            for ( std::list<SyntaxElement*>::iterator it = statements1->begin(); it != statements1->end(); ++it )
            {
                SyntaxElement* theSyntaxElement = *it;

                // Execute statement
	            result = theSyntaxElement->evaluateContent( env );
                
                // Print result if it is not an assign expression (==NULL)
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && !theSyntaxElement->isAssignment()
                        && result != NULL && result->getRevObject() != RevNullObject::getInstance() )
                {
                    std::ostringstream msg;
                    result->getRevObject().printValue(msg);
                    RBOUT( msg.str() );
                }
	 
	            // Free memory
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    result = NULL;  // discard result
                }
	 
	            // Catch signal
	            if ( !Signals::getSignals().isGood() )
                    break;
            }

            // Catch signals
            if ( Signals::getSignals().isSet(Signals::BREAK) )
            {
	                 Signals::getSignals().clearFlags();
	                 break;
            }
            else if ( Signals::getSignals().isSet(Signals::CONTINUE) )
            {
	                 Signals::getSignals().clearFlags();  // Just continue with next loop state
            }
        }
    }
    else if ( statementType == Return )
    {
        // Set RETURN signal and return expression value
        Signals::getSignals().set(Signals::RETURN);
        return expression->evaluateContent(env);
    }
    else if ( statementType == If )
    {
        // Process statements inside the if clause if expression is true
        if ( isTrue( expression, env ) )
        {
            for ( std::list<SyntaxElement*>::iterator it = statements1->begin(); it != statements1->end(); ++it )
            {
                // Execute statement
                result = (*it)->evaluateContent(env);
                
                // Print result if it is not an assign expression (==NULL)
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    std::ostringstream msg;
                    result->getRevObject().printValue(msg);
                    RBOUT( msg.str() );
                }

                // Free memory
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    result = NULL;  // discard result
                }
            }
        }
    }
    else if ( statementType == IfElse )
    {
        // Process statements inside the if clause if expression is true,
        // otherwise process statements in else clause
        if ( isTrue( expression, env ) )
        {
            for ( std::list<SyntaxElement*>::iterator it = statements1->begin(); it != statements1->end(); ++it )
            {
                // Execute statement
                result = (*it)->evaluateContent( env );
                
                // Print result if it is not an assign expression (==NULL)
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    std::ostringstream msg;
                    result->getRevObject().printValue(msg);
                    RBOUT( msg.str() );
                }
                
                // Free memory
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    result = NULL;  // discard result
                }
            }
        }
        else
        {
            for ( std::list<SyntaxElement*>::iterator it = statements2->begin(); it != statements2->end(); ++it )
            {
                // Execute statement
                result = (*it)->evaluateContent( env );
                
                // Print result if it is not an assign expression (==NULL)
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    std::ostringstream msg;
                    result->getRevObject().printValue(msg);
                    RBOUT( msg.str() );
                }
                    
                // Free memory
                if ( !Signals::getSignals().isSet( Signals::RETURN ) && result != NULL )
                {
                    result = NULL;  // discard result
                }
            }
        }
    }

    return result;
}
示例#13
0
/**
 * This function causes recursive execution of a syntax tree by calling the root to get its value.
 * As long as we return to the bison code, bison takes care of deleting the syntax tree. However,
 * if we encounter a quit() call, we delete the syntax tree ourselves and exit immediately.
 */
int RevLanguage::Parser::execute(SyntaxElement* root, Environment &env) const {

    // don't execute command if we are in checking mode
    if (RevLanguage::Parser::getParser().isChecking()) {
#ifdef DEBUG_PARSER
        std::cerr << "Command is not executed since parser is set checking mode.";
#endif
        return 0;
    }

#ifdef DEBUG_PARSER
    // Print syntax tree
    std::cerr << std::endl;
    std::cerr << "Syntax tree root before execution:\n";
    root->printValue(std::cerr);
    std::cerr << std::endl;
#endif

    // Declare a variable for the result
    RevPtr<RevVariable> result = NULL;

    //! Execute syntax tree
    try
    {
#ifdef DEBUG_PARSER
        printf("Parser getting the semantic value of the syntax tree...\n");
#endif
        result = root->evaluateContent(env);
    }
    catch (RbException& rbException)
    {

        std::ostringstream msg;

        // Catch a quit request
        if (rbException.getExceptionType() == RbException::QUIT)
        {
            delete( root);
            
#ifdef RB_MPI
            MPI::Finalize();
#endif
            
            exit(0);
        }

        // Catch a missing variable exception that might be interpreted as a request for
        // usage help on a function
        SyntaxVariable* rootPtr = dynamic_cast<SyntaxVariable*> ((SyntaxElement*) root);
        SyntaxVariable* theVariable = rootPtr;
        if (rbException.getExceptionType() == RbException::MISSING_VARIABLE && theVariable != NULL)
        {

            const std::string& fxnName = theVariable->getIdentifier();
            const std::vector<Function*>& functions = Workspace::userWorkspace().getFunctionTable().findFunctions(fxnName);
            if (functions.size() != 0) {
                for (std::vector<Function*>::const_iterator i = functions.begin(); i != functions.end(); i++) {
                    std::ostringstream s;
                    (*i)->printValue(s);
                    RBOUT(s.str());

                    // Uncommenting this as the function callSignature() does not produce the call signature despite its name
                    // -- Fredrik
                    // RBOUT( (*i)->callSignature() );
                }
                return 0;
            }
        }

        // All other exceptions
#ifdef DEBUG_PARSER
        printf("Caught an exception\n");
#endif
        rbException.print(msg);
        RBOUT(msg.str());

        // Return signal indicating problem
        return 2;
    }

    // Print result if the root is not an assign expression
    if (!root->isAssignment() && result != NULL && result->getRevObject() != RevNullObject::getInstance())
    {
        std::ostringstream msg;
        result->getRevObject().printValue(msg,true);
        RBOUT(msg.str());
    }

    // Warn if a return signal has been encountered
    // @todo Find out why the following lines do not work; they should
    //    if ( Signals::getSignals().isSet( Signals::RETURN ) )
    //        RBOUT( "WARNING: No function to return from" );
    Signals::getSignals().clearFlags();

    // Return success
    return 0;
}
示例#14
0
/**
 * Fit a variable into an argument according to the argument rule. If necessary and
 * appropriate, we do type conversion or type promotion.
 *
 *
 *
 * @todo To conform to the old code we change the required type of the incoming
 *       variable wrapper here. We need to change this so that we do not change
 *       the wrapper here, but make sure that if the argument variable is inserted
 *       in a member variable or container element slot, that the slot variable
 *       wrapper, which should be unique (not the same as the incoming variable
 *       wrapper), has the right required type.
 */
Argument ArgumentRule::fitArgument( Argument& arg, bool once ) const
{

    RevPtr<RevVariable> theVar = arg.getVariable();
    if ( evalType == BY_VALUE || theVar->isWorkspaceVariable() || theVar->getRevObject().isConstant() )
    {
        once = true;
    }
    
    
    for ( std::vector<TypeSpec>::const_iterator it = argTypeSpecs.begin(); it != argTypeSpecs.end(); ++it )
    {
        if ( evalType == BY_VALUE )
        {
            if ( theVar->getRevObject().isType( *it ) )
            {
                RevPtr<RevVariable> valueVar = RevPtr<RevVariable>( new RevVariable(theVar->getRevObject().clone(),arg.getLabel()) );
                return Argument( valueVar, getArgumentLabel(), false );
            }
            else if ( theVar->getRevObject().isConvertibleTo( *it, once ) != -1)
            {
                // Fit by type conversion. For now, we also modify the type of the incoming variable wrapper.
                RevObject* convertedObject = theVar->getRevObject().convertTo( *it );

                RevPtr<RevVariable> valueVar = RevPtr<RevVariable>( new RevVariable(convertedObject,arg.getLabel()) );
                return Argument( valueVar, getArgumentLabel(), false );
                
            }
        } // if (by-value)
        else
        {
            if ( theVar->getRevObject().isType( *it ) )
            {
                // For now, change the required type of the incoming variable wrapper
                theVar->setRequiredTypeSpec( *it );
            
                if ( !isEllipsis() )
                {
                    return Argument( theVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
                }
                else
                {
                    return Argument( theVar, arg.getLabel(), true );
                }
            
            }
            else if ( theVar->getRevObject().isConvertibleTo( *it, once ) != -1  && (*it).isDerivedOf( theVar->getRequiredTypeSpec() ))
            {
                // Fit by type conversion. For now, we also modify the type of the incoming variable wrapper.
                RevObject* convertedObject = theVar->getRevObject().convertTo( *it );
                theVar->replaceRevObject( convertedObject );
                theVar->setRequiredTypeSpec( *it );
                if ( !isEllipsis() )
                {
                    return Argument( theVar, getArgumentLabel(), false );
                }
                else
                {
                    return Argument( theVar, arg.getLabel(), false );
                }
            }
            else
            {
                // Fit by type conversion function
            
                const TypeSpec& typeFrom = theVar->getRevObject().getTypeSpec();
                const TypeSpec& typeTo   = *it;
            
                // create the function name
                std::string functionName = "_" + typeFrom.getType() + "2" + typeTo.getType();
                
                // Package arguments
                std::vector<Argument> args;
                Argument theArg = Argument( theVar, "arg" );
                args.push_back( theVar );
                
                Environment& env = Workspace::globalWorkspace();
            
                try
                {
                    Function* func = env.getFunction(functionName, args, once).clone();

                    // Allow the function to process the arguments
                    func->processArguments( args, once );
            
                    // Set the execution environment of the function
                    func->setExecutionEnviroment( &env );
                
                    // Evaluate the function
                    RevPtr<RevVariable> conversionVar = func->execute();
                
                    // free the memory
                    delete func;
                
                    conversionVar->setHiddenVariableState( true );
                    conversionVar->setRequiredTypeSpec( *it );
                
                    return Argument( conversionVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
                
                }
                catch (RbException e)
                {
                // we do nothing here
                }
                
            } // else (type conversion function)

            
        } // else (not by-value)

    }
    
    std::cerr << "Once = " << (once ? "TRUE" : "FALSE") << std::endl;
    
    throw RbException( "Argument type mismatch fitting a " + theVar->getRevObject().getType() + " argument to formal " +
                        getArgumentTypeSpec()[0].getType() + " " + getArgumentLabel() );
}
示例#15
0
/**
 * Test if argument is valid. The boolean flag 'once' is used to signal whether the argument matching
 * is done in a static or a dynamic context. If the rule is constant, then the argument matching
 * is done in a static context (evaluate-once context) regardless of the setting of the once flag.
 * If the argument is constant, we try type promotion if permitted by the variable required type.
 *
 * @todo See the TODOs for fitArgument(...)
 */
double ArgumentRule::isArgumentValid( Argument &arg, bool once) const
{
    
    RevPtr<RevVariable> theVar = arg.getVariable();
    if ( theVar == NULL )
    {
        return -1;
    }
    
    if ( evalType == BY_VALUE || theVar->isWorkspaceVariable() || ( theVar->getRevObject().isModelObject() && theVar->getRevObject().getDagNode()->getDagNodeType() == RevBayesCore::DagNode::CONSTANT) )
    {
        once = true;
    }
    
    if ( nodeType == STOCHASTIC && theVar->getRevObject().getDagNode()->getDagNodeType() != RevBayesCore::DagNode::STOCHASTIC )
    {
        return -1;
    }
    else if ( nodeType == DETERMINISTIC && theVar->getRevObject().getDagNode()->getDagNodeType() != RevBayesCore::DagNode::DETERMINISTIC )
    {
        return -1;
    }

    for ( std::vector<TypeSpec>::const_iterator it = argTypeSpecs.begin(); it != argTypeSpecs.end(); ++it )
    {
        if ( theVar->getRevObject().isType( *it ) )
        {
            return 0.0;
        }
        else if ( theVar->getRevObject().isConvertibleTo( *it, once ) != -1 && (*it).isDerivedOf( theVar->getRequiredTypeSpec() ) )
        {
            return theVar->getRevObject().isConvertibleTo( *it, once );
        }
        else if ( theVar->getRevObject().isConvertibleTo( *it, once ) != -1 && evalType == BY_VALUE )
        {
            return theVar->getRevObject().isConvertibleTo( *it, once );
        }

//        else if ( once == true &&
////                 !var->isAssignable() &&
//                  theVar->getRevObject().isConvertibleTo( *it, true ) != -1 &&
//                  (*it).isDerivedOf( theVar->getRequiredTypeSpec() )
//                )
//        {
//            return theVar->getRevObject().isConvertibleTo( *it, true );
//        }
        else if ( nodeType != STOCHASTIC )
        {
            
            const TypeSpec& typeFrom = theVar->getRevObject().getTypeSpec();
            const TypeSpec& typeTo   = *it;
            
            // create the function name
            std::string functionName = "_" + typeFrom.getType() + "2" + typeTo.getType();
            
            // Package arguments
            std::vector<Argument> args;
            Argument theArg = Argument( theVar, "arg" );
            args.push_back( theVar );
            
            Environment& env = Workspace::globalWorkspace();
            try
            {
                // we just want to check if the function exists and can be found
                env.getFunction(functionName, args, once);
                return 0.1;
            }
            catch (RbException e)
            {
                // we do nothing here
            }

        }
        
    }
    
    return -1;
}
示例#16
0
/**
 * Fit a variable into an argument according to the argument rule. If necessary and
 * appropriate, we do type conversion or type promotion.
 *
 * @todo The constant flag is currently not used correctly in ArgumentRule. Therefore,
 *       we ignore it here for now. This needs to be changed.
 *
 * @todo We need to check whether workspace objects with member variables are
 *       modifiable by the user.
 *
 * @todo To conform to the old code we change the required type of the incoming
 *       variable wrapper here. We need to change this so that we do not change
 *       the wrapper here, but make sure that if the argument variable is inserted
 *       in a member variable or container element slot, that the slot variable
 *       wrapper, which should be unique (not the same as the incoming variable
 *       wrapper), has the right required type.
 */
Argument ArgumentRule::fitArgument( Argument& arg, bool once ) const
{
    //    TODO: Use this code when the constant flag in ArgumentRule is used correctly
    //    if ( isConstant() || !theVar->isAssignable() )
    if ( evalType == BY_VALUE )
    {
        once = true;
    }
    
    RevPtr<Variable> theVar = arg.getVariable();
    
    for ( std::vector<TypeSpec>::const_iterator it = argTypeSpecs.begin(); it != argTypeSpecs.end(); ++it )
    {
        if ( theVar->getRevObject().isTypeSpec( *it ) )
        {
            // For now, change the required type of the incoming variable wrapper
            theVar->setRevObjectTypeSpec( *it );
            
            if ( !isEllipsis() )
                return Argument( theVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
            else
                return Argument( theVar, arg.getLabel(), true );
        }
        else if ( once == false &&
                 !theVar->isAssignable() &&
                 theVar->getRevObject().isConvertibleTo( *it, true ) &&
                 (*it).isDerivedOf( theVar->getRevObjectTypeSpec() )
                 )
        {
            // Fit by type promotion. For now, we also modify the type of the incoming variable wrapper.
            RevObject* convertedObject = theVar->getRevObject().convertTo( *it );
            theVar->setRevObject( convertedObject );
            theVar->setRevObjectTypeSpec( *it );
            if ( !isEllipsis() )
                return Argument( theVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
            else
                return Argument( theVar, arg.getLabel(), true );
        }
        else if ( theVar->getRevObject().isConvertibleTo( *it, once ) )
        {
            // Fit by type conversion
            if ( once || !theVar->getRevObject().hasDagNode() )
            {
                RevObject* convertedObject = theVar->getRevObject().convertTo( *it );
                Variable*  convertedVar    = new Variable( convertedObject );
                convertedVar->setRevObjectTypeSpec( *it );

                if ( !isEllipsis() )
                    return Argument( convertedVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
                else
                    return Argument( convertedVar, arg.getLabel(), true );
            }
            else
            {
                RevObject* conversionObject = theVar->getRevObject().convertTo( *it );
                conversionObject->makeConversionValue( theVar );
                Variable*  conversionVar    = new Variable( conversionObject );
                conversionVar->setRevObjectTypeSpec( *it );
                
                if ( !isEllipsis() )
                    return Argument( conversionVar, getArgumentLabel(), evalType == BY_CONSTANT_REFERENCE );
                else
                    return Argument( conversionVar, arg.getLabel(), true );
            }
        }
    }
    
    throw RbException( "Argument type mismatch fitting a " + theVar->getRevObject().getType() + " argument to formal " +
                        getArgumentTypeSpec()[0].getType() + " " + getArgumentLabel() );
}
/**
 * Evaluate semantic content.
 *
 * If dynamic == false, then we know that we only want to evaluate the function once,
 * and get a constant value back. For now, it does the same thing as
 * if dynamic == true, with two exceptions. First, it uses the evaluate function
 * with dynamic == false to evaluate its arguments. Second, it makes the return
 * value a constant value.
 *
 * If dynamic == true, then we know that we want
 * to evaluate the function repeatedly, as part of a deterministic variable.
 * Therefore, we need to make a deterministic variable with the function inside
 * it. Currently, this is the default implementation for the execute function
 * in RevLanguage::Function, but we may want to differentiate between the two
 * contexts later.
 *
 * @todo Support this function call context better
 */
RevPtr<RevVariable> SyntaxFunctionCall::evaluateContent( Environment& env, bool dynamic )
{
    
    // Package arguments
    std::vector<Argument> args;
    for ( std::list<SyntaxLabeledExpr*>::const_iterator it = arguments->begin(); it != arguments->end(); ++it )
    {
#ifdef DEBUG_PARSER
        printf( "Adding argument with label \"%s\".\n", (*i)->getLabel().c_str() );
#endif
        
        const RlString& theLabel = (*it)->getLabel();
        RevPtr<RevVariable> theVar = (*it)->getExpression().evaluateContent(env,dynamic);
        
        Argument theArg = Argument( theVar, theLabel.getValue() );
        args.push_back( theArg );
    }
    
    Function* func = NULL;
    if ( baseVariable == NULL )
    {
        // We are trying to find a function in the current environment
        
        // First we see if the function name corresponds to a user-defined variable
        // We can do this first because user-defined variables are not allowed to mask function names
        bool found = false;
        if ( env.existsVariable( functionName ) )
        {
            RevObject &theObject = env.getRevObject( functionName );
            
            if ( theObject.isType( Function::getClassTypeSpec() ) )
            {
                func = static_cast<Function*>( theObject.clone() );
                found = func->checkArguments(args, NULL, !dynamic);
            }
        }
        
        // If we cannot find the function name as a variable, it must be in the function table
        // This call will throw with a relevant message if the function is not found
        if ( !found )
        {
            func = env.getFunction(functionName, args, !dynamic).clone();
        }
        
        // Allow the function to process the arguments
        func->processArguments( args, !dynamic );
        
        // Set the execution environment of the function
        func->setExecutionEnviroment( &env );
    }
    else
    {
        // We are trying to find a member function
        
        // First we get the base variable
        RevPtr<RevVariable> theVar = baseVariable->evaluateContent( env, dynamic );
        
        // Now we get a reference to the member object inside
        RevObject &theMemberObject = theVar->getRevObject();
        
        const MethodTable& mt = theMemberObject.getMethods();
        
        Function* theFunction = mt.getFunction( functionName, args, !dynamic ).clone();
        theFunction->processArguments(args, !dynamic);
        
        MemberMethod* theMemberMethod = dynamic_cast<MemberMethod*>( theFunction );
        if ( theMemberMethod != NULL )
        {
            theMemberMethod->setMemberObject( theVar );
            func = theFunction;
        }
        else
        {
            delete theFunction;
            throw RbException("Error while trying to access member function/procedure.");
        }
        
    }
    
    // Evaluate the function
    RevPtr<RevVariable> funcReturnValue = func->execute();
    
    // free the memory of our copy
    delete func;
    
    if ( dynamic == false )
    {
        // Return the value, which is typically a deterministic variable with the function
        // inside it, although many functions return constant values or NULL (void).
        // To make sure the value is a constant and not a deterministic variable in this
        // context, we convert the return value here to a constant value before returning it.
        if ( funcReturnValue != NULL )
        {
            funcReturnValue->getRevObject().makeConstantValue();
        }
    }
    
    return funcReturnValue;
}
示例#18
0
/**
 * @brief Evaluate left-hand-side content
 *
 * This function is similar to evaluateContent(). However, we
 * do not throw an error if the variable does not exist in the
 * frame; instead, we create and return a new null variable.
 */
RevPtr<Variable> SyntaxVariable::evaluateLHSContent( Environment& env, const std::string& elemType )
{
    // Get static index. No dynamic evaluation here
    std::vector<size_t> oneOffsetIndices = computeStaticIndex( env );
    
    RevPtr<Variable> theVar;
    
    if ( baseVariable == NULL )
    {
        if ( functionCall != NULL )
        {
            // Get the return variable of the function call
            theVar = functionCall->evaluateContent( env );
        }
        else if ( expression != NULL )
        {
            // Get the return variable of the expression
            theVar = expression->evaluateContent( env );
        }
        else
        {
            // Find or create the variable
            if ( env.existsVariableInFrame( identifier ) )
                theVar = env.getVariable( identifier );
            else    // add it
            {
                if ( oneOffsetIndices.size() == 0 )
                    theVar = new Variable( NULL, identifier );
                else
                    theVar = new Variable( Workspace::userWorkspace().makeNewEmptyContainer( elemType, oneOffsetIndices.size() ), identifier );
                env.addVariable( identifier, theVar );
            }
        }
    }
    else
    {
        // Note that the function call is always NULL if there is
        // a base variable, because any variables that are base to
        // the function call are handled by the function call. Note
        // also that generic expressions can only occur in base
        // variables, so we need not worry about any expression if
        // we are not a base variable.
        
        // Get the base variable. Note that we do not create the variable in this case.
        theVar = baseVariable->evaluateContent( env );

        // Find member variable based on its name
        theVar = theVar->getRevObject().getMember( identifier );
    }
    
    // Get element if indices are provided.
    while ( !oneOffsetIndices.empty() )
    {
        // Get the element...
        if ( theVar->getRevObject().isTypeSpec( Container::RevObject::getClassTypeSpec() ) )
        {
            // ... from a container
            
            // Get the container indices
            std::vector<size_t> containerOneOffsetIndices;
            for ( size_t i = 0; i < theVar->getRevObject().getDim(); ++i )
            {
                if ( !oneOffsetIndices.empty() )
                {
                    containerOneOffsetIndices.push_back( oneOffsetIndices[0] );
                    oneOffsetIndices.erase( oneOffsetIndices.begin() );
                }
                else
                    containerOneOffsetIndices.push_back( 0 );
            }
            
            // Get the element using the findOrCreateElement function
            theVar = theVar->getRevObject().findOrCreateElement( containerOneOffsetIndices );
        }
        else
        {
            // ... or from a subscript operator
            
            // Note that we do not name the element here; either the member object gives out
            // a variable it names itself, or it gives out a temporary variable copy, which
            // should not be named. A subscript operator cannot be used to assign to a non-
            // existing variable.
            
            // Create the single argument for the index operator
            std::vector<Argument> args;
            RevPtr<Variable> indexVar = new Variable( new Natural( oneOffsetIndices[0] ) );
            args.push_back( Argument( indexVar ) );
            
            // Get the variable using the subscript operator function
            // TODO: This needs to be made generic for user-defined member objects
            theVar = theVar->getRevObject().executeMethod( "[]", args );
            
            // Erase the index
            oneOffsetIndices.erase( oneOffsetIndices.begin() );
        }
    }

    // Return the variable for assignment
    return theVar;
}
示例#19
0
/**
 * @brief Evaluate dynamic rhs content
 *
 * This function returns the semantic value of the variable expression
 * when it is part of a dynamic expression, that is, the right-hand side
 * of an equation (deterministic) or tilde (stochastic) assignment.
 *
 * It differs from the standard evaluateContent() in several ways. First,
 * control variables need to return clones of themselves (temporary
 * variables) rather than themselves, so that they are not included in
 * the DAG. Second, we cannot compute a static index for indexed variables.
 * Instead, we need to deliver an index conisting of variables resulting
 * from dynamic evaluation of the index variables. These need to be put
 * in a dynamic lookup variable.
 */
RevPtr<Variable> SyntaxVariable::evaluateDynamicContent( Environment& env)
{
    RevPtr<Variable> theVar;
    
    if ( baseVariable == NULL )
    {
        if ( functionCall != NULL )
        {
            // Get the dynamic return variable of the function call
            theVar = functionCall->evaluateDynamicContent( env );
        }
        else if ( expression  != NULL )
        {
            // Get the dynamic return variable of the expression
            theVar = expression->evaluateDynamicContent( env );
        }
        else
        {
            // Get variable from the environment (no dynamic version of identifier)
            theVar = env.getVariable( identifier );
        }
    }
    else
    {
        // Note that the function call is always NULL if there is
        // a base variable, because any variables that are base to
        // the function call are handled by the function call. Note
        // also that generic expressions can only occur in base
        // variables, so we need not worry about any expression if
        // we are not a base variable.
        
        // Get the base variable
        theVar = baseVariable->evaluateDynamicContent( env );
        
        // Find member variable (no dynamic version of identifier)
        theVar = theVar->getRevObject().getMember( identifier );
    }

    // Get dynamic index
    std::vector< RevPtr<Variable> > oneOffsetIndexVars = computeDynamicIndex( env );
    
    // Check if we need a dynamic lookup
    bool dynamicLookup = false;
    for ( std::vector< RevPtr<Variable> >::iterator it = oneOffsetIndexVars.begin(); it != oneOffsetIndexVars.end(); ++it )
    {
        if ( (*it)->getRevObject().hasDagNode() && (*it)->isAssignable() )
        {
            dynamicLookup = true;
            break;
        }
    }
    
    // If the variable we are looking up things in does not have a DAG node, we do not need a dynamic lookup regardless
    // If it does have a DAG node, we need a dynamic lookup if it is named, regardless of whether we have constant indices
    if ( theVar->getRevObject().hasDagNode() == false )
        dynamicLookup = false;
    else if ( theVar->isAssignable() )
        dynamicLookup = true;

    // Get dynamic element from container or subscript operator
    while ( !oneOffsetIndexVars.empty() )
    {
        // Get the element...
        if ( theVar->getRevObject().isTypeSpec( Container::RevObject::getClassTypeSpec() ) )
        {
            // ... from a container
            
            // Get the container index variables
            std::vector< RevPtr<Variable> > containerOneOffsetIndexVars;
            for ( size_t i = 0; i < theVar->getRevObject().getDim(); ++i )
            {
                if ( !oneOffsetIndexVars.empty() )
                {
                    containerOneOffsetIndexVars.push_back( oneOffsetIndexVars[0] );
                    oneOffsetIndexVars.erase( oneOffsetIndexVars.begin() );
                }
                else
                    containerOneOffsetIndexVars.push_back( new Variable( new Natural( 0 ) ) );
            }
            
            if ( dynamicLookup )
            {
                // Make a dynamic element lookup
                theVar = new Variable( theVar->getRevObject().makeElementLookup( theVar, containerOneOffsetIndexVars ) );
            }
            else
            {
                // We want a static element lookup

                // Get the container indices statically
                std::vector<size_t> containerOneOffsetIndices;
                for ( size_t i = 0; i < containerOneOffsetIndexVars.size(); ++i )
                {
                    containerOneOffsetIndices.push_back( getIndex( containerOneOffsetIndexVars[i], env ) );
                }
                
                // Get the element using the getElement function
                theVar = theVar->getRevObject().getElement( containerOneOffsetIndices );
            }
        }
        else
        {
            // ... or from a subscript operator
            
            // Note that we do not name the element here; either the member object gives out
            // a variable it names itself, or it gives out a temporary variable copy, which
            // should not be named
            
            // Create the single argument for the index operator (statically always for now)
            std::vector<Argument> args;
            args.push_back( Argument( new Variable( new Natural( getIndex( oneOffsetIndexVars[0], env ) ) ) ) );

           // Get the variable using the subscript operator function
            // TODO: This needs to be made generic for user-defined member objects
            // TODO: This needs to check that there is a subscript operator function and not procedure,
            // and then return a dynamic element lookup
            theVar = theVar->getRevObject().executeMethod( "[]", args );
            
            // Erase the index
            oneOffsetIndexVars.erase( oneOffsetIndexVars.begin() );
        }
    }
    
    // Check whether we have a control variable and make a clone in that case
    if ( theVar->isControlVar() )
        theVar = new Variable( theVar->getRevObject().clone() );
    
    // Return the variable for assignment
    return theVar;
}