/** * 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; }
/** * @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; }