/**
 * 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;
}
示例#2
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;
}