/** * Initialize loop state. Here we evaluate the in-expression and * make sure it is a container with at least one dimension. We will * use the first dimension of the container to get the values for * the loop variable. We also add the loop variable to the environment. */ void SyntaxForLoop::initializeLoop( Environment& env ) { assert ( nextIndex == 0 ); // Check that we are not running already // Evaluate expression and check that we get a vector const RevPtr<RevVariable>& theVar = inExpression->evaluateContent(env); const RevObject& theValue = theVar->getRevObject(); // Check that it is a container (the first dimension of which we will use) stateSpace = dynamic_cast<Container*>( theValue.clone() ); if ( stateSpace == NULL ) { throw RbException( "The 'in' expression does not evaluate to a container" ); } // Add the loop variable to the environment, if it is not already there if ( !env.existsVariable( varName ) ) env.addVariable( varName, new RevVariable( NULL) ); // Set the local smart pointer to the loop variable loopVariable = env.getVariable( varName ); // Initialize nextValue nextIndex = 1; }
/** * @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; }
/** * @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<RevVariable> SyntaxVariable::evaluateLHSContent( Environment& env, const std::string& elemType ) { RevPtr<RevVariable> theVar; // Find or create the variable if ( env.existsVariable( identifier ) ) { theVar = env.getVariable( identifier ); } else // add it { theVar = new RevVariable( NULL, identifier ); env.addVariable( identifier, theVar ); } // Return the variable for assignment return theVar; }
/** Execute function */ RevPtr<RevVariable> Func_module::execute( void ) { /* Get the module */ std::string moduleName = static_cast<const RlString &>( args[0].getVariable()->getRevObject() ).getValue(); const Module& mod = ModuleSystem::getModuleSystem().getModule( moduleName ); Environment *execEnv = env; if ( args[1].getVariable()->getRevObject() != RevNullObject::getInstance() ) { std::string ns = static_cast<const RlString &>( args[1].getVariable()->getRevObject() ).getValue(); execEnv = env->getChildEnvironment( ns ); } // WorkspaceVector<RevObject> *moduleArgs = new WorkspaceVector<RevObject>(); for (size_t i = 2; i < args.size(); ++i) { // moduleArgs->push_back( args[i].getVariable()->getRevObject() ); if ( args[i].getLabel() != "" ) { if ( !execEnv->existsVariable( args[i].getLabel() ) ) { execEnv->addVariable(args[i].getLabel(), args[i].getVariable() ); } } else { std::cout << "Empty ellipsis argument label.\n"; } } // execEnv->addVariable("args", moduleArgs); // if ( !execEnv->existsVariable("namespace") ) // { // execEnv->addVariable("namespace", new RlString(ns) ); // } /* Initialize */ const std::vector<std::string>& commandLines = mod.getCommandLines(); std::string command = ""; int lineNumber = 0; int result = 0; // result from processing of last command RBOUT("Processing module \"" + moduleName + "\""); /* Command-processing loop */ for ( std::vector<std::string>::const_iterator it = commandLines.begin(); it != commandLines.end(); ++it) { // Get a line const std::string& line = *it; lineNumber++; // If previous result was 1 (append to command), we do this if ( result == 1 ) command += line; else command = line; // Process the line and record result result = Parser::getParser().processCommand( command, execEnv ); if ( result == 2 ) { std::ostringstream msg; msg << "Problem processing line " << lineNumber << " in module \"" << moduleName << "\""; throw RbException( msg.str() ); } } /* Return control */ RBOUT("Processing of module \"" + moduleName + "\" completed"); return NULL; }
/** * @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; }