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