RObject *RObjectList::findObjects (const QStringList &path, RObjectSearchMap *matches, const QString &op) { RK_TRACE (OBJECTS); RK_ASSERT (op == "$"); if (path.value (1) == "::") { RObject *environment = findPackage (path[0]); if (!environment) return 0; return environment->findObjects (path.mid (2), matches, "$"); } else if (path.value (1) == ":::") { RObject *environment = findPackage (path[0]); if (environment) environment = static_cast<REnvironmentObject*> (environment)->namespaceEnvironment (); if (!environment) environment = orphan_namespaces->findOrphanNamespace (path[0]); if (!environment) return 0; return environment->findObjects (path.mid (2), matches, "$"); } else if (path.value (0) == ".GlobalEnv") { if (path.length () > 1) return getGlobalEnv ()->findObjects (path.mid (2), matches, "$"); else if (matches) matches->insert (path.value (0), getGlobalEnv ()); // no return, here: At least one more match will be found in base else return getGlobalEnv (); } // no namespace given. Search all environments for matches RObject *found = getGlobalEnv ()->findObjects (path, matches, "$"); if (found && !matches) return found; for (int i = 0; i < childmap.size (); ++i) { found = childmap[i]->findObjects (path, matches, "$"); if (found && !matches) return found; } return 0; }
Value LocalScope::getVar(VarNameRef name) const { if (name == "_current") return table; if (name == "_super") return parent.getVar("_current"); if (name == "_global") return getGlobalEnv().getVar("_current"); JSON::INode *nd = table->getVariable(name); if (nd == 0) return parent.getVar(name); else return nd; }
void RObjectList::updateEnvironments (const QStringList &_env_names, bool force_globalenv_update) { RK_TRACE (OBJECTS); RObjectMap newchildmap; QStringList env_names = _env_names; if (!env_names.isEmpty ()) { QString dummy = env_names.takeFirst (); RK_ASSERT (dummy == ".GlobalEnv"); if (force_globalenv_update) { // for now, we only update the .GlobalEnv. All others we assume to be static getGlobalEnv ()->updateFromR (update_chain); } } else { RK_ASSERT (!env_names.isEmpty ()); } // find which items are new, and copy the old ones for (int i = 0; i < env_names.count (); ++i) { QString name = env_names[i]; RObject *obj = findChildByName (name); if (obj && (i > 0) && (env_names.lastIndexOf (name, i-1) > -1)) { // duplicate environment names can happen (e.g. if a data.frame is attached multiple times) obj = 0; // only copy the old item once } if (!obj) { obj = createTopLevelEnvironment (name); RKGlobals::tracker ()->beginAddObject (obj, this, i); childmap.insert (i, obj); RKGlobals::tracker ()->endAddObject (obj, this, i); } newchildmap.insert (i, obj); } // check which envs have been removed or changed position for (int i = 0; i < childmap.size (); ++i) { // do *not* cache the childmap.size ()! We may change it in the loop. RObject *obj = childmap[i]; int new_pos = newchildmap.indexOf (obj); if (new_pos < 0) { // environment is gone RK_DEBUG (OBJECTS, DL_INFO, "removing toplevel environment %s from list", obj->getShortName ().toLatin1 ().data ()); if (RKGlobals::tracker ()->removeObject (obj, 0, true)) --i; else (newchildmap.insert (i, obj)); } else if (new_pos != i) { // this call is rather expensive, all in all, but fortunately called very rarely moveChild (obj, i, new_pos); } } RK_DO (RK_ASSERT (childmap == newchildmap), OBJECTS, DL_DEBUG); // this is an expensive assert, hence wrapping it inside RK_DO }